[reflection] Use MonoError in mono_get_object_from_blob
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 #ifndef DISABLE_REFLECTION_EMIT
428 static char*
429 image_strdup (MonoImage *image, const char *s)
430 {
431         MONO_REQ_GC_NEUTRAL_MODE;
432
433         if (image)
434                 return mono_image_strdup (image, s);
435         else
436                 return g_strdup (s);
437 }
438 #endif
439
440 #define image_g_new(image,struct_type, n_structs)               \
441     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
442
443 #define image_g_new0(image,struct_type, n_structs)              \
444     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
445
446
447 static void
448 alloc_table (MonoDynamicTable *table, guint nrows)
449 {
450         MONO_REQ_GC_NEUTRAL_MODE;
451
452         table->rows = nrows;
453         g_assert (table->columns);
454         if (nrows + 1 >= table->alloc_rows) {
455                 while (nrows + 1 >= table->alloc_rows) {
456                         if (table->alloc_rows == 0)
457                                 table->alloc_rows = 16;
458                         else
459                                 table->alloc_rows *= 2;
460                 }
461
462                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
463         }
464 }
465
466 static void
467 make_room_in_stream (MonoDynamicStream *stream, int size)
468 {
469         MONO_REQ_GC_NEUTRAL_MODE;
470
471         if (size <= stream->alloc_size)
472                 return;
473         
474         while (stream->alloc_size <= size) {
475                 if (stream->alloc_size < 4096)
476                         stream->alloc_size = 4096;
477                 else
478                         stream->alloc_size *= 2;
479         }
480         
481         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
482 }
483
484 static guint32
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
486 {
487         MONO_REQ_GC_NEUTRAL_MODE;
488
489         guint32 idx;
490         guint32 len;
491         gpointer oldkey, oldval;
492
493         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494                 return GPOINTER_TO_UINT (oldval);
495
496         len = strlen (str) + 1;
497         idx = sh->index;
498         
499         make_room_in_stream (sh, idx + len);
500
501         /*
502          * We strdup the string even if we already copy them in sh->data
503          * so that the string pointers in the hash remain valid even if
504          * we need to realloc sh->data. We may want to avoid that later.
505          */
506         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507         memcpy (sh->data + idx, str, len);
508         sh->index += len;
509         return idx;
510 }
511
512 static guint32
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
514 {
515         MONO_REQ_GC_UNSAFE_MODE;
516
517         char *name = mono_string_to_utf8 (str);
518         guint32 idx;
519         idx = string_heap_insert (sh, name);
520         g_free (name);
521         return idx;
522 }
523
524 #ifndef DISABLE_REFLECTION_EMIT
525 static void
526 string_heap_init (MonoDynamicStream *sh)
527 {
528         MONO_REQ_GC_NEUTRAL_MODE;
529
530         sh->index = 0;
531         sh->alloc_size = 4096;
532         sh->data = (char *)g_malloc (4096);
533         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534         string_heap_insert (sh, "");
535 }
536 #endif
537
538 static guint32
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
540 {
541         MONO_REQ_GC_NEUTRAL_MODE;
542
543         guint32 idx;
544         
545         make_room_in_stream (stream, stream->index + len);
546         memcpy (stream->data + stream->index, data, len);
547         idx = stream->index;
548         stream->index += len;
549         /* 
550          * align index? Not without adding an additional param that controls it since
551          * we may store a blob value in pieces.
552          */
553         return idx;
554 }
555
556 static guint32
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
558 {
559         MONO_REQ_GC_NEUTRAL_MODE;
560
561         guint32 idx;
562         
563         make_room_in_stream (stream, stream->index + len);
564         memset (stream->data + stream->index, 0, len);
565         idx = stream->index;
566         stream->index += len;
567         return idx;
568 }
569
570 static void
571 stream_data_align (MonoDynamicStream *stream)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         char buf [4] = {0};
576         guint32 count = stream->index % 4;
577
578         /* we assume the stream data will be aligned */
579         if (count)
580                 mono_image_add_stream_data (stream, buf, 4 - count);
581 }
582
583 #ifndef DISABLE_REFLECTION_EMIT
584 static int
585 mono_blob_entry_hash (const char* str)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         guint len, h;
590         const char *end;
591         len = mono_metadata_decode_blob_size (str, &str);
592         if (len > 0) {
593                 end = str + len;
594                 h = *str;
595                 for (str += 1; str < end; str++)
596                         h = (h << 5) - h + *str;
597                 return h;
598         } else {
599                 return 0;
600         }
601 }
602
603 static gboolean
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605         MONO_REQ_GC_NEUTRAL_MODE;
606
607         int len, len2;
608         const char *end1;
609         const char *end2;
610         len = mono_metadata_decode_blob_size (str1, &end1);
611         len2 = mono_metadata_decode_blob_size (str2, &end2);
612         if (len != len2)
613                 return 0;
614         return memcmp (end1, end2, len) == 0;
615 }
616 #endif
617 static guint32
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
619 {
620         MONO_REQ_GC_NEUTRAL_MODE;
621
622         guint32 idx;
623         char *copy;
624         gpointer oldkey, oldval;
625
626         copy = (char *)g_malloc (s1+s2);
627         memcpy (copy, b1, s1);
628         memcpy (copy + s1, b2, s2);
629         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
630                 g_free (copy);
631                 idx = GPOINTER_TO_UINT (oldval);
632         } else {
633                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634                 mono_image_add_stream_data (&assembly->blob, b2, s2);
635                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
636         }
637         return idx;
638 }
639
640 static guint32
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
642 {
643         MONO_REQ_GC_NEUTRAL_MODE;
644
645         char blob_size [8];
646         char *b = blob_size;
647         guint32 size = buf->p - buf->buf;
648         /* store length */
649         g_assert (size <= (buf->end - buf->buf));
650         mono_metadata_encode_value (size, b, &b);
651         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
652 }
653
654 /*
655  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656  * dest may be misaligned.
657  */
658 static void
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660         MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
662         int elem;
663
664         for (elem = 0; elem < nelem; ++elem) {
665                 switch (len) {
666                 case 1:
667                         *dest = *val;
668                         break;
669                 case 2:
670                         dest [0] = val [1];
671                         dest [1] = val [0];
672                         break;
673                 case 4:
674                         dest [0] = val [3];
675                         dest [1] = val [2];
676                         dest [2] = val [1];
677                         dest [3] = val [0];
678                         break;
679                 case 8:
680                         dest [0] = val [7];
681                         dest [1] = val [6];
682                         dest [2] = val [5];
683                         dest [3] = val [4];
684                         dest [4] = val [3];
685                         dest [5] = val [2];
686                         dest [6] = val [1];
687                         dest [7] = val [0];
688                         break;
689                 default:
690                         g_assert_not_reached ();
691                 }
692                 dest += len;
693                 val += len;
694         }
695 #else
696         memcpy (dest, val, len * nelem);
697 #endif
698 }
699
700 static guint32
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
702 {
703         MONO_REQ_GC_UNSAFE_MODE;
704         
705         char blob_size [64];
706         char *b = blob_size;
707         guint32 idx = 0, len;
708
709         len = str->length * 2;
710         mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
712         {
713                 char *swapped = g_malloc (2 * mono_string_length (str));
714                 const char *p = (const char*)mono_string_chars (str);
715
716                 swap_with_size (swapped, p, 2, mono_string_length (str));
717                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
718                 g_free (swapped);
719         }
720 #else
721         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
722 #endif
723         return idx;
724 }
725
726 #ifndef DISABLE_REFLECTION_EMIT
727 static MonoClass *
728 default_class_from_mono_type (MonoType *type)
729 {
730         MONO_REQ_GC_NEUTRAL_MODE;
731
732         switch (type->type) {
733         case MONO_TYPE_OBJECT:
734                 return mono_defaults.object_class;
735         case MONO_TYPE_VOID:
736                 return mono_defaults.void_class;
737         case MONO_TYPE_BOOLEAN:
738                 return mono_defaults.boolean_class;
739         case MONO_TYPE_CHAR:
740                 return mono_defaults.char_class;
741         case MONO_TYPE_I1:
742                 return mono_defaults.sbyte_class;
743         case MONO_TYPE_U1:
744                 return mono_defaults.byte_class;
745         case MONO_TYPE_I2:
746                 return mono_defaults.int16_class;
747         case MONO_TYPE_U2:
748                 return mono_defaults.uint16_class;
749         case MONO_TYPE_I4:
750                 return mono_defaults.int32_class;
751         case MONO_TYPE_U4:
752                 return mono_defaults.uint32_class;
753         case MONO_TYPE_I:
754                 return mono_defaults.int_class;
755         case MONO_TYPE_U:
756                 return mono_defaults.uint_class;
757         case MONO_TYPE_I8:
758                 return mono_defaults.int64_class;
759         case MONO_TYPE_U8:
760                 return mono_defaults.uint64_class;
761         case MONO_TYPE_R4:
762                 return mono_defaults.single_class;
763         case MONO_TYPE_R8:
764                 return mono_defaults.double_class;
765         case MONO_TYPE_STRING:
766                 return mono_defaults.string_class;
767         default:
768                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769                 g_assert_not_reached ();
770         }
771         
772         return NULL;
773 }
774 #endif
775
776 /*
777  * mono_class_get_ref_info:
778  *
779  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
780  */
781 gpointer
782 mono_class_get_ref_info (MonoClass *klass)
783 {
784         MONO_REQ_GC_UNSAFE_MODE;
785
786         if (klass->ref_info_handle == 0)
787                 return NULL;
788         else
789                 return mono_gchandle_get_target (klass->ref_info_handle);
790 }
791
792 void
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
794 {
795         MONO_REQ_GC_UNSAFE_MODE;
796
797         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798         g_assert (klass->ref_info_handle != 0);
799 }
800
801 void
802 mono_class_free_ref_info (MonoClass *klass)
803 {
804         MONO_REQ_GC_NEUTRAL_MODE;
805
806         if (klass->ref_info_handle) {
807                 mono_gchandle_free (klass->ref_info_handle);
808                 klass->ref_info_handle = 0;
809         }
810 }
811
812 static void
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
814 {
815         MONO_REQ_GC_NEUTRAL_MODE;
816
817         int i;
818         MonoGenericInst *class_inst;
819         MonoClass *klass;
820
821         g_assert (gclass);
822
823         class_inst = gclass->context.class_inst;
824
825         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826         klass = gclass->container_class;
827         sigbuffer_add_value (buf, klass->byval_arg.type);
828         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
829
830         sigbuffer_add_value (buf, class_inst->type_argc);
831         for (i = 0; i < class_inst->type_argc; ++i)
832                 encode_type (assembly, class_inst->type_argv [i], buf);
833
834 }
835
836 static void
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
838 {
839         MONO_REQ_GC_NEUTRAL_MODE;
840
841         if (!type) {
842                 g_assert_not_reached ();
843                 return;
844         }
845                 
846         if (type->byref)
847                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
848
849         switch (type->type){
850         case MONO_TYPE_VOID:
851         case MONO_TYPE_BOOLEAN:
852         case MONO_TYPE_CHAR:
853         case MONO_TYPE_I1:
854         case MONO_TYPE_U1:
855         case MONO_TYPE_I2:
856         case MONO_TYPE_U2:
857         case MONO_TYPE_I4:
858         case MONO_TYPE_U4:
859         case MONO_TYPE_I8:
860         case MONO_TYPE_U8:
861         case MONO_TYPE_R4:
862         case MONO_TYPE_R8:
863         case MONO_TYPE_I:
864         case MONO_TYPE_U:
865         case MONO_TYPE_STRING:
866         case MONO_TYPE_OBJECT:
867         case MONO_TYPE_TYPEDBYREF:
868                 sigbuffer_add_value (buf, type->type);
869                 break;
870         case MONO_TYPE_PTR:
871                 sigbuffer_add_value (buf, type->type);
872                 encode_type (assembly, type->data.type, buf);
873                 break;
874         case MONO_TYPE_SZARRAY:
875                 sigbuffer_add_value (buf, type->type);
876                 encode_type (assembly, &type->data.klass->byval_arg, buf);
877                 break;
878         case MONO_TYPE_VALUETYPE:
879         case MONO_TYPE_CLASS: {
880                 MonoClass *k = mono_class_from_mono_type (type);
881
882                 if (k->generic_container) {
883                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884                         encode_generic_class (assembly, gclass, buf);
885                 } else {
886                         /*
887                          * Make sure we use the correct type.
888                          */
889                         sigbuffer_add_value (buf, k->byval_arg.type);
890                         /*
891                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892                          * otherwise two typerefs could point to the same type, leading to
893                          * verification errors.
894                          */
895                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
896                 }
897                 break;
898         }
899         case MONO_TYPE_ARRAY:
900                 sigbuffer_add_value (buf, type->type);
901                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902                 sigbuffer_add_value (buf, type->data.array->rank);
903                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904                 sigbuffer_add_value (buf, 0);
905                 break;
906         case MONO_TYPE_GENERICINST:
907                 encode_generic_class (assembly, type->data.generic_class, buf);
908                 break;
909         case MONO_TYPE_VAR:
910         case MONO_TYPE_MVAR:
911                 sigbuffer_add_value (buf, type->type);
912                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
913                 break;
914         default:
915                 g_error ("need to encode type %x", type->type);
916         }
917 }
918
919 static void
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
921 {
922         MONO_REQ_GC_UNSAFE_MODE;
923
924         if (!type) {
925                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
926                 return;
927         }
928
929         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
930 }
931
932 static void
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
934 {
935         MONO_REQ_GC_UNSAFE_MODE;
936
937         int i;
938
939         if (modreq) {
940                 for (i = 0; i < mono_array_length (modreq); ++i) {
941                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
944                 }
945         }
946         if (modopt) {
947                 for (i = 0; i < mono_array_length (modopt); ++i) {
948                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
951                 }
952         }
953 }
954
955 #ifndef DISABLE_REFLECTION_EMIT
956 static guint32
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
958 {
959         MONO_REQ_GC_UNSAFE_MODE;
960
961         SigBuffer buf;
962         int i;
963         guint32 nparams =  sig->param_count;
964         guint32 idx;
965
966         if (!assembly->save)
967                 return 0;
968
969         sigbuffer_init (&buf, 32);
970         /*
971          * FIXME: vararg, explicit_this, differenc call_conv values...
972          */
973         idx = sig->call_convention;
974         if (sig->hasthis)
975                 idx |= 0x20; /* hasthis */
976         if (sig->generic_param_count)
977                 idx |= 0x10; /* generic */
978         sigbuffer_add_byte (&buf, idx);
979         if (sig->generic_param_count)
980                 sigbuffer_add_value (&buf, sig->generic_param_count);
981         sigbuffer_add_value (&buf, nparams);
982         encode_type (assembly, sig->ret, &buf);
983         for (i = 0; i < nparams; ++i) {
984                 if (i == sig->sentinelpos)
985                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986                 encode_type (assembly, sig->params [i], &buf);
987         }
988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989         sigbuffer_free (&buf);
990         return idx;
991 }
992 #endif
993
994 static guint32
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
996 {
997         MONO_REQ_GC_UNSAFE_MODE;
998
999         /*
1000          * FIXME: reuse code from method_encode_signature().
1001          */
1002         SigBuffer buf;
1003         int i;
1004         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1005         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1007         guint32 idx;
1008
1009         sigbuffer_init (&buf, 32);
1010         /* LAMESPEC: all the call conv spec is foobared */
1011         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012         if (mb->call_conv & 2)
1013                 idx |= 0x5; /* vararg */
1014         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015                 idx |= 0x20; /* hasthis */
1016         if (ngparams)
1017                 idx |= 0x10; /* generic */
1018         sigbuffer_add_byte (&buf, idx);
1019         if (ngparams)
1020                 sigbuffer_add_value (&buf, ngparams);
1021         sigbuffer_add_value (&buf, nparams + notypes);
1022         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023         encode_reflection_type (assembly, mb->rtype, &buf);
1024         for (i = 0; i < nparams; ++i) {
1025                 MonoArray *modreq = NULL;
1026                 MonoArray *modopt = NULL;
1027                 MonoReflectionType *pt;
1028
1029                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035                 encode_reflection_type (assembly, pt, &buf);
1036         }
1037         if (notypes)
1038                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039         for (i = 0; i < notypes; ++i) {
1040                 MonoReflectionType *pt;
1041
1042                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043                 encode_reflection_type (assembly, pt, &buf);
1044         }
1045
1046         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047         sigbuffer_free (&buf);
1048         return idx;
1049 }
1050
1051 static guint32
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1053 {
1054         MONO_REQ_GC_UNSAFE_MODE;
1055
1056         MonoDynamicTable *table;
1057         guint32 *values;
1058         guint32 idx, sig_idx;
1059         guint nl = mono_array_length (ilgen->locals);
1060         SigBuffer buf;
1061         int i;
1062
1063         sigbuffer_init (&buf, 32);
1064         sigbuffer_add_value (&buf, 0x07);
1065         sigbuffer_add_value (&buf, nl);
1066         for (i = 0; i < nl; ++i) {
1067                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1068                 
1069                 if (lb->is_pinned)
1070                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1071                 
1072                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1073         }
1074         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075         sigbuffer_free (&buf);
1076
1077         if (assembly->standalonesig_cache == NULL)
1078                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1080         if (idx)
1081                 return idx;
1082
1083         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084         idx = table->next_idx ++;
1085         table->rows ++;
1086         alloc_table (table, table->rows);
1087         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1088
1089         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1090
1091         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1092
1093         return idx;
1094 }
1095
1096 static guint32
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         guint32 num_clauses = 0;
1102         int i;
1103
1104         MonoILExceptionInfo *ex_info;
1105         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107                 if (ex_info->handlers)
1108                         num_clauses += mono_array_length (ex_info->handlers);
1109                 else
1110                         num_clauses++;
1111         }
1112
1113         return num_clauses;
1114 }
1115
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1119 {
1120         MONO_REQ_GC_UNSAFE_MODE;
1121
1122         MonoExceptionClause *clauses;
1123         MonoExceptionClause *clause;
1124         MonoILExceptionInfo *ex_info;
1125         MonoILExceptionBlock *ex_block;
1126         guint32 finally_start;
1127         int i, j, clause_index;;
1128
1129         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1130
1131         clause_index = 0;
1132         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134                 finally_start = ex_info->start + ex_info->len;
1135                 if (!ex_info->handlers)
1136                         continue;
1137                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139                         clause = &(clauses [clause_index]);
1140
1141                         clause->flags = ex_block->type;
1142                         clause->try_offset = ex_info->start;
1143
1144                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145                                 clause->try_len = finally_start - ex_info->start;
1146                         else
1147                                 clause->try_len = ex_info->len;
1148                         clause->handler_offset = ex_block->start;
1149                         clause->handler_len = ex_block->len;
1150                         if (ex_block->extype) {
1151                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1152                         } else {
1153                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154                                         clause->data.filter_offset = ex_block->filter_offset;
1155                                 else
1156                                         clause->data.filter_offset = 0;
1157                         }
1158                         finally_start = ex_block->start + ex_block->len;
1159
1160                         clause_index ++;
1161                 }
1162         }
1163
1164         return clauses;
1165 }
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1167
1168 /**
1169  * method_encode_code:
1170  *
1171  * @assembly the assembly
1172  * @mb the managed MethodBuilder
1173  * @error set on error
1174  *
1175  * Note that the return value is not sensible if @error is set.
1176  */
1177 static guint32
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1179 {
1180         MONO_REQ_GC_UNSAFE_MODE;
1181
1182         char flags = 0;
1183         guint32 idx;
1184         guint32 code_size;
1185         gint32 max_stack, i;
1186         gint32 num_locals = 0;
1187         gint32 num_exception = 0;
1188         gint maybe_small;
1189         guint32 fat_flags;
1190         char fat_header [12];
1191         guint32 int_value;
1192         guint16 short_value;
1193         guint32 local_sig = 0;
1194         guint32 header_size = 12;
1195         MonoArray *code;
1196
1197         mono_error_init (error);
1198
1199         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1201                 return 0;
1202
1203         /*if (mb->name)
1204                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1205         if (mb->ilgen) {
1206                 code = mb->ilgen->code;
1207                 code_size = mb->ilgen->code_len;
1208                 max_stack = mb->ilgen->max_stack;
1209                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210                 if (mb->ilgen->ex_handlers)
1211                         num_exception = method_count_clauses (mb->ilgen);
1212         } else {
1213                 code = mb->code;
1214                 if (code == NULL){
1215                         char *name = mono_string_to_utf8 (mb->name);
1216                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1218                         g_free (str);
1219                         g_free (name);
1220                         return 0;
1221                 }
1222
1223                 code_size = mono_array_length (code);
1224                 max_stack = 8; /* we probably need to run a verifier on the code... */
1225         }
1226
1227         stream_data_align (&assembly->code);
1228
1229         /* check for exceptions, maxstack, locals */
1230         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1231         if (maybe_small) {
1232                 if (code_size < 64 && !(code_size & 1)) {
1233                         flags = (code_size << 2) | 0x2;
1234                 } else if (code_size < 32 && (code_size & 1)) {
1235                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1236                 } else {
1237                         goto fat_header;
1238                 }
1239                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240                 /* add to the fixup todo list */
1241                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244                 return assembly->text_rva + idx;
1245         } 
1246 fat_header:
1247         if (num_locals)
1248                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1249         /* 
1250          * FIXME: need to set also the header size in fat_flags.
1251          * (and more sects and init locals flags)
1252          */
1253         fat_flags =  0x03;
1254         if (num_exception)
1255                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256         if (mb->init_locals)
1257                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258         fat_header [0] = fat_flags;
1259         fat_header [1] = (header_size / 4 ) << 4;
1260         short_value = GUINT16_TO_LE (max_stack);
1261         memcpy (fat_header + 2, &short_value, 2);
1262         int_value = GUINT32_TO_LE (code_size);
1263         memcpy (fat_header + 4, &int_value, 4);
1264         int_value = GUINT32_TO_LE (local_sig);
1265         memcpy (fat_header + 8, &int_value, 4);
1266         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267         /* add to the fixup todo list */
1268         if (mb->ilgen && mb->ilgen->num_token_fixups)
1269                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1270         
1271         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272         if (num_exception) {
1273                 unsigned char sheader [4];
1274                 MonoILExceptionInfo * ex_info;
1275                 MonoILExceptionBlock * ex_block;
1276                 int j;
1277
1278                 stream_data_align (&assembly->code);
1279                 /* always use fat format for now */
1280                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281                 num_exception *= 6 * sizeof (guint32);
1282                 num_exception += 4; /* include the size of the header */
1283                 sheader [1] = num_exception & 0xff;
1284                 sheader [2] = (num_exception >> 8) & 0xff;
1285                 sheader [3] = (num_exception >> 16) & 0xff;
1286                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287                 /* fat header, so we are already aligned */
1288                 /* reverse order */
1289                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291                         if (ex_info->handlers) {
1292                                 int finally_start = ex_info->start + ex_info->len;
1293                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1294                                         guint32 val;
1295                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1296                                         /* the flags */
1297                                         val = GUINT32_TO_LE (ex_block->type);
1298                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1299                                         /* try offset */
1300                                         val = GUINT32_TO_LE (ex_info->start);
1301                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302                                         /* need fault, too, probably */
1303                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1305                                         else
1306                                                 val = GUINT32_TO_LE (ex_info->len);
1307                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308                                         /* handler offset */
1309                                         val = GUINT32_TO_LE (ex_block->start);
1310                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1311                                         /* handler len */
1312                                         val = GUINT32_TO_LE (ex_block->len);
1313                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314                                         finally_start = ex_block->start + ex_block->len;
1315                                         if (ex_block->extype) {
1316                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1317                                         } else {
1318                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319                                                         val = ex_block->filter_offset;
1320                                                 else
1321                                                         val = 0;
1322                                         }
1323                                         val = GUINT32_TO_LE (val);
1324                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1326                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1327                                 }
1328                         } else {
1329                                 g_error ("No clauses for ex info block %d", i);
1330                         }
1331                 }
1332         }
1333         return assembly->text_rva + idx;
1334 }
1335
1336 static guint32
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1338 {
1339         MONO_REQ_GC_NEUTRAL_MODE;
1340
1341         int i;
1342         MonoDynamicTable *table;
1343         guint32 *values;
1344         
1345         table = &assembly->tables [table_idx];
1346
1347         g_assert (col < table->columns);
1348
1349         values = table->values + table->columns;
1350         for (i = 1; i <= table->rows; ++i) {
1351                 if (values [col] == token)
1352                         return i;
1353                 values += table->columns;
1354         }
1355         return 0;
1356 }
1357
1358 /*
1359  * LOCKING: Acquires the loader lock. 
1360  */
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1363 {
1364         MONO_REQ_GC_NEUTRAL_MODE;
1365
1366         MonoCustomAttrInfo* res;
1367
1368         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1369
1370         if (!res)
1371                 return NULL;
1372
1373         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1374         res->cached = 0;
1375         return res;
1376 }
1377
1378 static gboolean
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1380 {
1381         MONO_REQ_GC_UNSAFE_MODE;
1382
1383         /* FIXME: Need to do more checks */
1384         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1386
1387                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1388                         return FALSE;
1389         }
1390
1391         return TRUE;
1392 }
1393
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1396 {
1397         MONO_REQ_GC_UNSAFE_MODE;
1398
1399         int i, index, count, not_visible;
1400         MonoCustomAttrInfo *ainfo;
1401         MonoReflectionCustomAttr *cattr;
1402
1403         if (!cattrs)
1404                 return NULL;
1405         /* FIXME: check in assembly the Run flag is set */
1406
1407         count = mono_array_length (cattrs);
1408
1409         /* Skip nonpublic attributes since MS.NET seems to do the same */
1410         /* FIXME: This needs to be done more globally */
1411         not_visible = 0;
1412         for (i = 0; i < count; ++i) {
1413                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414                 if (!custom_attr_visible (image, cattr))
1415                         not_visible ++;
1416         }
1417         count -= not_visible;
1418
1419         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1420
1421         ainfo->image = image;
1422         ainfo->num_attrs = count;
1423         ainfo->cached = alloc_img != NULL;
1424         index = 0;
1425         for (i = 0; i < count; ++i) {
1426                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427                 if (custom_attr_visible (image, cattr)) {
1428                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430                         ainfo->attrs [index].ctor = cattr->ctor->method;
1431                         ainfo->attrs [index].data = saved;
1432                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1433                         index ++;
1434                 }
1435         }
1436
1437         return ainfo;
1438 }
1439
1440 #ifndef DISABLE_REFLECTION_EMIT
1441 /*
1442  * LOCKING: Acquires the loader lock. 
1443  */
1444 static void
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1446 {
1447         MONO_REQ_GC_UNSAFE_MODE;
1448
1449         MonoCustomAttrInfo *ainfo, *tmp;
1450
1451         if (!cattrs || !mono_array_length (cattrs))
1452                 return;
1453
1454         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1455
1456         mono_loader_lock ();
1457         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1458         if (tmp)
1459                 mono_custom_attrs_free (tmp);
1460         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461         mono_loader_unlock ();
1462
1463 }
1464 #endif
1465
1466 void
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1468 {
1469         MONO_REQ_GC_NEUTRAL_MODE;
1470
1471         if (ainfo && !ainfo->cached)
1472                 g_free (ainfo);
1473 }
1474
1475 /*
1476  * idx is the table index of the object
1477  * type is one of MONO_CUSTOM_ATTR_*
1478  */
1479 static gboolean
1480 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1481 {
1482         MONO_REQ_GC_UNSAFE_MODE;
1483
1484         MonoDynamicTable *table;
1485         MonoReflectionCustomAttr *cattr;
1486         guint32 *values;
1487         guint32 count, i, token;
1488         char blob_size [6];
1489         char *p = blob_size;
1490         
1491         mono_error_init (error);
1492
1493         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1494         if (!cattrs)
1495                 return TRUE;
1496         count = mono_array_length (cattrs);
1497         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1498         table->rows += count;
1499         alloc_table (table, table->rows);
1500         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1501         idx <<= MONO_CUSTOM_ATTR_BITS;
1502         idx |= type;
1503         for (i = 0; i < count; ++i) {
1504                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1505                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1506                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1507                 if (!mono_error_ok (error)) goto fail;
1508                 type = mono_metadata_token_index (token);
1509                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1510                 switch (mono_metadata_token_table (token)) {
1511                 case MONO_TABLE_METHOD:
1512                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1513                         /*
1514                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1515                          * method, not the one returned by mono_image_create_token ().
1516                          */
1517                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1518                         break;
1519                 case MONO_TABLE_MEMBERREF:
1520                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1521                         break;
1522                 default:
1523                         g_warning ("got wrong token in custom attr");
1524                         continue;
1525                 }
1526                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1527                 p = blob_size;
1528                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1529                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1530                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1531                 values += MONO_CUSTOM_ATTR_SIZE;
1532                 ++table->next_idx;
1533         }
1534
1535         return TRUE;
1536
1537 fail:
1538         return FALSE;
1539 }
1540
1541 static void
1542 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1543 {
1544         MONO_REQ_GC_UNSAFE_MODE;
1545
1546         MonoDynamicTable *table;
1547         guint32 *values;
1548         guint32 count, i, idx;
1549         MonoReflectionPermissionSet *perm;
1550
1551         if (!permissions)
1552                 return;
1553
1554         count = mono_array_length (permissions);
1555         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1556         table->rows += count;
1557         alloc_table (table, table->rows);
1558
1559         for (i = 0; i < mono_array_length (permissions); ++i) {
1560                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1561
1562                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1563
1564                 idx = mono_metadata_token_index (parent_token);
1565                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1566                 switch (mono_metadata_token_table (parent_token)) {
1567                 case MONO_TABLE_TYPEDEF:
1568                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1569                         break;
1570                 case MONO_TABLE_METHOD:
1571                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1572                         break;
1573                 case MONO_TABLE_ASSEMBLY:
1574                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1575                         break;
1576                 default:
1577                         g_assert_not_reached ();
1578                 }
1579
1580                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1581                 values [MONO_DECL_SECURITY_PARENT] = idx;
1582                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1583
1584                 ++table->next_idx;
1585         }
1586 }
1587
1588 /*
1589  * Fill in the MethodDef and ParamDef tables for a method.
1590  * This is used for both normal methods and constructors.
1591  */
1592 static gboolean
1593 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1594 {
1595         MONO_REQ_GC_UNSAFE_MODE;
1596
1597         MonoDynamicTable *table;
1598         guint32 *values;
1599         guint i, count;
1600
1601         mono_error_init (error);
1602
1603         /* room in this table is already allocated */
1604         table = &assembly->tables [MONO_TABLE_METHOD];
1605         *mb->table_idx = table->next_idx ++;
1606         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1607         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1608         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609         values [MONO_METHOD_FLAGS] = mb->attrs;
1610         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1611         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1612         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1613         if (!mono_error_ok (error))
1614                 return FALSE;
1615
1616         table = &assembly->tables [MONO_TABLE_PARAM];
1617         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1618
1619         mono_image_add_decl_security (assembly, 
1620                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1621
1622         if (mb->pinfo) {
1623                 MonoDynamicTable *mtable;
1624                 guint32 *mvalues;
1625                 
1626                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1627                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1628                 
1629                 count = 0;
1630                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1631                         if (mono_array_get (mb->pinfo, gpointer, i))
1632                                 count++;
1633                 }
1634                 table->rows += count;
1635                 alloc_table (table, table->rows);
1636                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1637                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1638                         MonoReflectionParamBuilder *pb;
1639                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1640                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1641                                 values [MONO_PARAM_SEQUENCE] = i;
1642                                 if (pb->name != NULL) {
1643                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1644                                 } else {
1645                                         values [MONO_PARAM_NAME] = 0;
1646                                 }
1647                                 values += MONO_PARAM_SIZE;
1648                                 if (pb->marshal_info) {
1649                                         mtable->rows++;
1650                                         alloc_table (mtable, mtable->rows);
1651                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1652                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1653                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1654                                 }
1655                                 pb->table_idx = table->next_idx++;
1656                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1657                                         guint32 field_type = 0;
1658                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1659                                         mtable->rows ++;
1660                                         alloc_table (mtable, mtable->rows);
1661                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1662                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1663                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1664                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1665                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1666                                 }
1667                         }
1668                 }
1669         }
1670
1671         return TRUE;
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 static gboolean
1676 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1677 {
1678         MONO_REQ_GC_UNSAFE_MODE;
1679
1680         mono_error_init (error);
1681         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682
1683         rmb->ilgen = mb->ilgen;
1684         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1685         return_val_if_nok (error, FALSE);
1686         rmb->parameters = mb->parameters;
1687         rmb->generic_params = mb->generic_params;
1688         rmb->generic_container = mb->generic_container;
1689         rmb->opt_types = NULL;
1690         rmb->pinfo = mb->pinfo;
1691         rmb->attrs = mb->attrs;
1692         rmb->iattrs = mb->iattrs;
1693         rmb->call_conv = mb->call_conv;
1694         rmb->code = mb->code;
1695         rmb->type = mb->type;
1696         rmb->name = mb->name;
1697         rmb->table_idx = &mb->table_idx;
1698         rmb->init_locals = mb->init_locals;
1699         rmb->skip_visibility = FALSE;
1700         rmb->return_modreq = mb->return_modreq;
1701         rmb->return_modopt = mb->return_modopt;
1702         rmb->param_modreq = mb->param_modreq;
1703         rmb->param_modopt = mb->param_modopt;
1704         rmb->permissions = mb->permissions;
1705         rmb->mhandle = mb->mhandle;
1706         rmb->nrefs = 0;
1707         rmb->refs = NULL;
1708
1709         if (mb->dll) {
1710                 rmb->charset = mb->charset;
1711                 rmb->extra_flags = mb->extra_flags;
1712                 rmb->native_cc = mb->native_cc;
1713                 rmb->dllentry = mb->dllentry;
1714                 rmb->dll = mb->dll;
1715         }
1716
1717         return TRUE;
1718 }
1719
1720 static gboolean
1721 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1722 {
1723         MONO_REQ_GC_UNSAFE_MODE;
1724
1725         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1726
1727         mono_error_init (error);
1728
1729         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1730
1731         rmb->ilgen = mb->ilgen;
1732         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1733         return_val_if_nok (error, FALSE);
1734         rmb->parameters = mb->parameters;
1735         rmb->generic_params = NULL;
1736         rmb->generic_container = NULL;
1737         rmb->opt_types = NULL;
1738         rmb->pinfo = mb->pinfo;
1739         rmb->attrs = mb->attrs;
1740         rmb->iattrs = mb->iattrs;
1741         rmb->call_conv = mb->call_conv;
1742         rmb->code = NULL;
1743         rmb->type = mb->type;
1744         rmb->name = mono_string_new (mono_domain_get (), name);
1745         rmb->table_idx = &mb->table_idx;
1746         rmb->init_locals = mb->init_locals;
1747         rmb->skip_visibility = FALSE;
1748         rmb->return_modreq = NULL;
1749         rmb->return_modopt = NULL;
1750         rmb->param_modreq = mb->param_modreq;
1751         rmb->param_modopt = mb->param_modopt;
1752         rmb->permissions = mb->permissions;
1753         rmb->mhandle = mb->mhandle;
1754         rmb->nrefs = 0;
1755         rmb->refs = NULL;
1756
1757         return TRUE;
1758 }
1759
1760 static void
1761 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1762 {
1763         MONO_REQ_GC_UNSAFE_MODE;
1764
1765         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1766
1767         rmb->ilgen = mb->ilgen;
1768         rmb->rtype = mb->rtype;
1769         rmb->parameters = mb->parameters;
1770         rmb->generic_params = NULL;
1771         rmb->generic_container = NULL;
1772         rmb->opt_types = NULL;
1773         rmb->pinfo = NULL;
1774         rmb->attrs = mb->attrs;
1775         rmb->iattrs = 0;
1776         rmb->call_conv = mb->call_conv;
1777         rmb->code = NULL;
1778         rmb->type = (MonoObject *) mb->owner;
1779         rmb->name = mb->name;
1780         rmb->table_idx = NULL;
1781         rmb->init_locals = mb->init_locals;
1782         rmb->skip_visibility = mb->skip_visibility;
1783         rmb->return_modreq = NULL;
1784         rmb->return_modopt = NULL;
1785         rmb->param_modreq = NULL;
1786         rmb->param_modopt = NULL;
1787         rmb->permissions = NULL;
1788         rmb->mhandle = mb->mhandle;
1789         rmb->nrefs = 0;
1790         rmb->refs = NULL;
1791 }       
1792 #endif
1793
1794 static gboolean
1795 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1796 {
1797         MONO_REQ_GC_UNSAFE_MODE;
1798
1799         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1800         MonoDynamicTable *table;
1801         guint32 *values;
1802         guint32 tok;
1803         MonoReflectionMethod *m;
1804         int i;
1805
1806         mono_error_init (error);
1807
1808         if (!mb->override_methods)
1809                 return TRUE;
1810
1811         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1812                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1813
1814                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1815                 table->rows ++;
1816                 alloc_table (table, table->rows);
1817                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1818                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1819                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1820
1821                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1822                 return_val_if_nok (error, FALSE);
1823
1824                 switch (mono_metadata_token_table (tok)) {
1825                 case MONO_TABLE_MEMBERREF:
1826                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1827                         break;
1828                 case MONO_TABLE_METHOD:
1829                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1830                         break;
1831                 default:
1832                         g_assert_not_reached ();
1833                 }
1834                 values [MONO_METHODIMPL_DECLARATION] = tok;
1835         }
1836
1837         return TRUE;
1838 }
1839
1840 #ifndef DISABLE_REFLECTION_EMIT
1841 static gboolean
1842 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1843 {
1844         MONO_REQ_GC_UNSAFE_MODE;
1845
1846         MonoDynamicTable *table;
1847         guint32 *values;
1848         ReflectionMethodBuilder rmb;
1849         int i;
1850
1851         mono_error_init (error);
1852
1853         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1854             !mono_image_basic_method (&rmb, assembly, error))
1855                 return FALSE;
1856
1857         mb->table_idx = *rmb.table_idx;
1858
1859         if (mb->dll) { /* It's a P/Invoke method */
1860                 guint32 moduleref;
1861                 /* map CharSet values to on-disk values */
1862                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1863                 int extra_flags = mb->extra_flags;
1864                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1865                 table->rows ++;
1866                 alloc_table (table, table->rows);
1867                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1868                 
1869                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1870                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1871                 if (mb->dllentry)
1872                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1873                 else
1874                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1875                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1876                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1877                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1878                         table->rows ++;
1879                         alloc_table (table, table->rows);
1880                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1881                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1882                 }
1883         }
1884
1885         if (mb->generic_params) {
1886                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1887                 table->rows += mono_array_length (mb->generic_params);
1888                 alloc_table (table, table->rows);
1889                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1890                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1891
1892                         mono_image_get_generic_param_info (
1893                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1894                 }
1895         }
1896
1897         return TRUE;
1898 }
1899
1900 static gboolean
1901 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 {
1903         MONO_REQ_GC_UNSAFE_MODE;
1904
1905         ReflectionMethodBuilder rmb;
1906
1907         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1908                 return FALSE;
1909
1910         if (!mono_image_basic_method (&rmb, assembly, error))
1911                 return FALSE;
1912
1913         mb->table_idx = *rmb.table_idx;
1914
1915         return TRUE;
1916 }
1917 #endif
1918
1919 static char*
1920 type_get_fully_qualified_name (MonoType *type)
1921 {
1922         MONO_REQ_GC_NEUTRAL_MODE;
1923
1924         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1925 }
1926
1927 static char*
1928 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1929 {
1930         MONO_REQ_GC_UNSAFE_MODE;
1931
1932         MonoClass *klass;
1933         MonoAssembly *ta;
1934
1935         klass = mono_class_from_mono_type (type);
1936         if (!klass) 
1937                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1938         ta = klass->image->assembly;
1939         if (assembly_is_dynamic (ta) || (ta == ass)) {
1940                 if (klass->generic_class || klass->generic_container)
1941                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1942                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1943                 else
1944                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1945         }
1946
1947         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1948 }
1949
1950 #ifndef DISABLE_REFLECTION_EMIT
1951 /*field_image is the image to which the eventual custom mods have been encoded against*/
1952 static guint32
1953 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1954 {
1955         MONO_REQ_GC_NEUTRAL_MODE;
1956
1957         SigBuffer buf;
1958         guint32 idx, i, token;
1959
1960         if (!assembly->save)
1961                 return 0;
1962
1963         sigbuffer_init (&buf, 32);
1964         
1965         sigbuffer_add_value (&buf, 0x06);
1966         /* encode custom attributes before the type */
1967         if (type->num_mods) {
1968                 for (i = 0; i < type->num_mods; ++i) {
1969                         if (field_image) {
1970                                 MonoError error;
1971                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1972                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1973
1974                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1975                         } else {
1976                                 token = type->modifiers [i].token;
1977                         }
1978
1979                         if (type->modifiers [i].required)
1980                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1981                         else
1982                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1983
1984                         sigbuffer_add_value (&buf, token);
1985                 }
1986         }
1987         encode_type (assembly, type, &buf);
1988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1989         sigbuffer_free (&buf);
1990         return idx;
1991 }
1992 #endif
1993
1994 static guint32
1995 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1996 {
1997         MONO_REQ_GC_UNSAFE_MODE;
1998
1999         SigBuffer buf;
2000         guint32 idx;
2001         guint32 typespec = 0;
2002         MonoType *type;
2003         MonoClass *klass;
2004
2005         init_type_builder_generics (fb->type);
2006
2007         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
2008         klass = mono_class_from_mono_type (type);
2009
2010         sigbuffer_init (&buf, 32);
2011         
2012         sigbuffer_add_value (&buf, 0x06);
2013         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2014         /* encode custom attributes before the type */
2015
2016         if (klass->generic_container)
2017                 typespec = create_typespec (assembly, type);
2018
2019         if (typespec) {
2020                 MonoGenericClass *gclass;
2021                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2022                 encode_generic_class (assembly, gclass, &buf);
2023         } else {
2024                 encode_type (assembly, type, &buf);
2025         }
2026         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2027         sigbuffer_free (&buf);
2028         return idx;
2029 }
2030
2031 static guint32
2032 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2033 {
2034         MONO_REQ_GC_UNSAFE_MODE;
2035
2036         char blob_size [64];
2037         char *b = blob_size;
2038         char *box_val;
2039         char* buf;
2040         guint32 idx = 0, len = 0, dummy = 0;
2041
2042         buf = (char *)g_malloc (64);
2043         if (!val) {
2044                 *ret_type = MONO_TYPE_CLASS;
2045                 len = 4;
2046                 box_val = (char*)&dummy;
2047         } else {
2048                 box_val = ((char*)val) + sizeof (MonoObject);
2049                 *ret_type = val->vtable->klass->byval_arg.type;
2050         }
2051 handle_enum:
2052         switch (*ret_type) {
2053         case MONO_TYPE_BOOLEAN:
2054         case MONO_TYPE_U1:
2055         case MONO_TYPE_I1:
2056                 len = 1;
2057                 break;
2058         case MONO_TYPE_CHAR:
2059         case MONO_TYPE_U2:
2060         case MONO_TYPE_I2:
2061                 len = 2;
2062                 break;
2063         case MONO_TYPE_U4:
2064         case MONO_TYPE_I4:
2065         case MONO_TYPE_R4:
2066                 len = 4;
2067                 break;
2068         case MONO_TYPE_U8:
2069         case MONO_TYPE_I8:
2070                 len = 8;
2071                 break;
2072         case MONO_TYPE_R8:
2073                 len = 8;
2074                 break;
2075         case MONO_TYPE_VALUETYPE: {
2076                 MonoClass *klass = val->vtable->klass;
2077                 
2078                 if (klass->enumtype) {
2079                         *ret_type = mono_class_enum_basetype (klass)->type;
2080                         goto handle_enum;
2081                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2082                         len = 8;
2083                 } else 
2084                         g_error ("we can't encode valuetypes, we should have never reached this line");
2085                 break;
2086         }
2087         case MONO_TYPE_CLASS:
2088                 break;
2089         case MONO_TYPE_STRING: {
2090                 MonoString *str = (MonoString*)val;
2091                 /* there is no signature */
2092                 len = str->length * 2;
2093                 mono_metadata_encode_value (len, b, &b);
2094 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2095                 {
2096                         char *swapped = g_malloc (2 * mono_string_length (str));
2097                         const char *p = (const char*)mono_string_chars (str);
2098
2099                         swap_with_size (swapped, p, 2, mono_string_length (str));
2100                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2101                         g_free (swapped);
2102                 }
2103 #else
2104                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2105 #endif
2106
2107                 g_free (buf);
2108                 return idx;
2109         }
2110         case MONO_TYPE_GENERICINST:
2111                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2112                 goto handle_enum;
2113         default:
2114                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2115         }
2116
2117         /* there is no signature */
2118         mono_metadata_encode_value (len, b, &b);
2119 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2120         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2121         swap_with_size (blob_size, box_val, len, 1);
2122         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2123 #else
2124         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2125 #endif
2126
2127         g_free (buf);
2128         return idx;
2129 }
2130
2131 static guint32
2132 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2133 {
2134         MONO_REQ_GC_UNSAFE_MODE;
2135
2136         char *str;
2137         SigBuffer buf;
2138         guint32 idx, len;
2139
2140         sigbuffer_init (&buf, 32);
2141
2142         sigbuffer_add_value (&buf, minfo->type);
2143
2144         switch (minfo->type) {
2145         case MONO_NATIVE_BYVALTSTR:
2146         case MONO_NATIVE_BYVALARRAY:
2147                 sigbuffer_add_value (&buf, minfo->count);
2148                 break;
2149         case MONO_NATIVE_LPARRAY:
2150                 if (minfo->eltype || minfo->has_size) {
2151                         sigbuffer_add_value (&buf, minfo->eltype);
2152                         if (minfo->has_size) {
2153                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2154                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2155
2156                                 /* LAMESPEC: ElemMult is undocumented */
2157                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2158                         }
2159                 }
2160                 break;
2161         case MONO_NATIVE_SAFEARRAY:
2162                 if (minfo->eltype)
2163                         sigbuffer_add_value (&buf, minfo->eltype);
2164                 break;
2165         case MONO_NATIVE_CUSTOM:
2166                 if (minfo->guid) {
2167                         str = mono_string_to_utf8 (minfo->guid);
2168                         len = strlen (str);
2169                         sigbuffer_add_value (&buf, len);
2170                         sigbuffer_add_mem (&buf, str, len);
2171                         g_free (str);
2172                 } else {
2173                         sigbuffer_add_value (&buf, 0);
2174                 }
2175                 /* native type name */
2176                 sigbuffer_add_value (&buf, 0);
2177                 /* custom marshaler type name */
2178                 if (minfo->marshaltype || minfo->marshaltyperef) {
2179                         if (minfo->marshaltyperef)
2180                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2181                         else
2182                                 str = mono_string_to_utf8 (minfo->marshaltype);
2183                         len = strlen (str);
2184                         sigbuffer_add_value (&buf, len);
2185                         sigbuffer_add_mem (&buf, str, len);
2186                         g_free (str);
2187                 } else {
2188                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2189                         sigbuffer_add_value (&buf, 0);
2190                 }
2191                 if (minfo->mcookie) {
2192                         str = mono_string_to_utf8 (minfo->mcookie);
2193                         len = strlen (str);
2194                         sigbuffer_add_value (&buf, len);
2195                         sigbuffer_add_mem (&buf, str, len);
2196                         g_free (str);
2197                 } else {
2198                         sigbuffer_add_value (&buf, 0);
2199                 }
2200                 break;
2201         default:
2202                 break;
2203         }
2204         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2205         sigbuffer_free (&buf);
2206         return idx;
2207 }
2208
2209 static void
2210 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2211 {
2212         MONO_REQ_GC_UNSAFE_MODE;
2213
2214         MonoDynamicTable *table;
2215         guint32 *values;
2216
2217         /* maybe this fixup should be done in the C# code */
2218         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2219                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2220         table = &assembly->tables [MONO_TABLE_FIELD];
2221         fb->table_idx = table->next_idx ++;
2222         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2223         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2224         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2225         values [MONO_FIELD_FLAGS] = fb->attrs;
2226         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2227
2228         if (fb->offset != -1) {
2229                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2230                 table->rows ++;
2231                 alloc_table (table, table->rows);
2232                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2233                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2234                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2235         }
2236         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2237                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2238                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2239                 table->rows ++;
2240                 alloc_table (table, table->rows);
2241                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2242                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2243                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2244                 values [MONO_CONSTANT_TYPE] = field_type;
2245                 values [MONO_CONSTANT_PADDING] = 0;
2246         }
2247         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2248                 guint32 rva_idx;
2249                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2250                 table->rows ++;
2251                 alloc_table (table, table->rows);
2252                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2253                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2254                 /*
2255                  * We store it in the code section because it's simpler for now.
2256                  */
2257                 if (fb->rva_data) {
2258                         if (mono_array_length (fb->rva_data) >= 10)
2259                                 stream_data_align (&assembly->code);
2260                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2261                 } else
2262                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2263                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2264         }
2265         if (fb->marshal_info) {
2266                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2267                 table->rows ++;
2268                 alloc_table (table, table->rows);
2269                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2270                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2271                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2272         }
2273 }
2274
2275 static guint32
2276 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2277 {
2278         MONO_REQ_GC_UNSAFE_MODE;
2279
2280         SigBuffer buf;
2281         guint32 nparams = 0;
2282         MonoReflectionMethodBuilder *mb = fb->get_method;
2283         MonoReflectionMethodBuilder *smb = fb->set_method;
2284         guint32 idx, i;
2285
2286         if (mb && mb->parameters)
2287                 nparams = mono_array_length (mb->parameters);
2288         if (!mb && smb && smb->parameters)
2289                 nparams = mono_array_length (smb->parameters) - 1;
2290         sigbuffer_init (&buf, 32);
2291         if (fb->call_conv & 0x20)
2292                 sigbuffer_add_byte (&buf, 0x28);
2293         else
2294                 sigbuffer_add_byte (&buf, 0x08);
2295         sigbuffer_add_value (&buf, nparams);
2296         if (mb) {
2297                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2298                 for (i = 0; i < nparams; ++i) {
2299                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2300                         encode_reflection_type (assembly, pt, &buf);
2301                 }
2302         } else if (smb && smb->parameters) {
2303                 /* the property type is the last param */
2304                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2305                 for (i = 0; i < nparams; ++i) {
2306                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2307                         encode_reflection_type (assembly, pt, &buf);
2308                 }
2309         } else {
2310                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2311         }
2312
2313         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2314         sigbuffer_free (&buf);
2315         return idx;
2316 }
2317
2318 static void
2319 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2320 {
2321         MONO_REQ_GC_UNSAFE_MODE;
2322
2323         MonoDynamicTable *table;
2324         guint32 *values;
2325         guint num_methods = 0;
2326         guint32 semaidx;
2327
2328         /* 
2329          * we need to set things in the following tables:
2330          * PROPERTYMAP (info already filled in _get_type_info ())
2331          * PROPERTY    (rows already preallocated in _get_type_info ())
2332          * METHOD      (method info already done with the generic method code)
2333          * METHODSEMANTICS
2334          * CONSTANT
2335          */
2336         table = &assembly->tables [MONO_TABLE_PROPERTY];
2337         pb->table_idx = table->next_idx ++;
2338         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2339         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2340         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2341         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2342
2343         /* FIXME: we still don't handle 'other' methods */
2344         if (pb->get_method) num_methods ++;
2345         if (pb->set_method) num_methods ++;
2346
2347         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2348         table->rows += num_methods;
2349         alloc_table (table, table->rows);
2350
2351         if (pb->get_method) {
2352                 semaidx = table->next_idx ++;
2353                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2354                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2355                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2356                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2357         }
2358         if (pb->set_method) {
2359                 semaidx = table->next_idx ++;
2360                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2361                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2362                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2363                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2364         }
2365         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2366                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2367                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2368                 table->rows ++;
2369                 alloc_table (table, table->rows);
2370                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2371                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2372                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2373                 values [MONO_CONSTANT_TYPE] = field_type;
2374                 values [MONO_CONSTANT_PADDING] = 0;
2375         }
2376 }
2377
2378 static void
2379 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2380 {
2381         MONO_REQ_GC_UNSAFE_MODE;
2382
2383         MonoDynamicTable *table;
2384         guint32 *values;
2385         guint num_methods = 0;
2386         guint32 semaidx;
2387
2388         /* 
2389          * we need to set things in the following tables:
2390          * EVENTMAP (info already filled in _get_type_info ())
2391          * EVENT    (rows already preallocated in _get_type_info ())
2392          * METHOD      (method info already done with the generic method code)
2393          * METHODSEMANTICS
2394          */
2395         table = &assembly->tables [MONO_TABLE_EVENT];
2396         eb->table_idx = table->next_idx ++;
2397         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2398         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2399         values [MONO_EVENT_FLAGS] = eb->attrs;
2400         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2401
2402         /*
2403          * FIXME: we still don't handle 'other' methods 
2404          */
2405         if (eb->add_method) num_methods ++;
2406         if (eb->remove_method) num_methods ++;
2407         if (eb->raise_method) num_methods ++;
2408
2409         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410         table->rows += num_methods;
2411         alloc_table (table, table->rows);
2412
2413         if (eb->add_method) {
2414                 semaidx = table->next_idx ++;
2415                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2417                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2418                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2419         }
2420         if (eb->remove_method) {
2421                 semaidx = table->next_idx ++;
2422                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2424                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2425                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2426         }
2427         if (eb->raise_method) {
2428                 semaidx = table->next_idx ++;
2429                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2430                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2431                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2432                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2433         }
2434 }
2435
2436 static void
2437 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2438 {
2439         MONO_REQ_GC_UNSAFE_MODE;
2440
2441         MonoDynamicTable *table;
2442         guint32 num_constraints, i;
2443         guint32 *values;
2444         guint32 table_idx;
2445
2446         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2447         num_constraints = gparam->iface_constraints ?
2448                 mono_array_length (gparam->iface_constraints) : 0;
2449         table->rows += num_constraints;
2450         if (gparam->base_type)
2451                 table->rows++;
2452         alloc_table (table, table->rows);
2453
2454         if (gparam->base_type) {
2455                 table_idx = table->next_idx ++;
2456                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2457
2458                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2459                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2460                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2461         }
2462
2463         for (i = 0; i < num_constraints; i++) {
2464                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2465                         gparam->iface_constraints, gpointer, i);
2466
2467                 table_idx = table->next_idx ++;
2468                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2469
2470                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2471                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2472                         assembly, mono_reflection_type_get_handle (constraint));
2473         }
2474 }
2475
2476 static void
2477 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2478 {
2479         MONO_REQ_GC_UNSAFE_MODE;
2480
2481         GenericParamTableEntry *entry;
2482
2483         /*
2484          * The GenericParam table must be sorted according to the `owner' field.
2485          * We need to do this sorting prior to writing the GenericParamConstraint
2486          * table, since we have to use the final GenericParam table indices there
2487          * and they must also be sorted.
2488          */
2489
2490         entry = g_new0 (GenericParamTableEntry, 1);
2491         entry->owner = owner;
2492         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2493         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2494         entry->gparam = gparam;
2495         
2496         g_ptr_array_add (assembly->gen_params, entry);
2497 }
2498
2499 static gboolean
2500 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2501 {
2502         MONO_REQ_GC_UNSAFE_MODE;
2503
2504         MonoDynamicTable *table;
2505         MonoGenericParam *param;
2506         guint32 *values;
2507         guint32 table_idx;
2508
2509         mono_error_init (error);
2510
2511         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2512         table_idx = table->next_idx ++;
2513         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2514
2515         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2516
2517         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2518         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2519         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2520         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2521
2522         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2523                 return FALSE;
2524
2525         encode_constraints (entry->gparam, table_idx, assembly);
2526
2527         return TRUE;
2528 }
2529
2530 static guint32
2531 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2532 {
2533         MONO_REQ_GC_UNSAFE_MODE;
2534
2535         MonoDynamicTable *table;
2536         guint32 token;
2537         guint32 *values;
2538         guint32 cols [MONO_ASSEMBLY_SIZE];
2539         const char *pubkey;
2540         guint32 publen;
2541
2542         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2543                 return token;
2544
2545         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2546                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2547                 token = table->next_idx ++;
2548                 table->rows ++;
2549                 alloc_table (table, table->rows);
2550                 values = table->values + token * MONO_MODULEREF_SIZE;
2551                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2552
2553                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2554                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2555                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2556
2557                 return token;
2558         }
2559         
2560         if (assembly_is_dynamic (image->assembly))
2561                 /* FIXME: */
2562                 memset (cols, 0, sizeof (cols));
2563         else {
2564                 /* image->assembly->image is the manifest module */
2565                 image = image->assembly->image;
2566                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2567         }
2568
2569         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2570         token = table->next_idx ++;
2571         table->rows ++;
2572         alloc_table (table, table->rows);
2573         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2574         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2575         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2576         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2577         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2578         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2579         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2580         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2581         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2582
2583         if (strcmp ("", image->assembly->aname.culture)) {
2584                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2585                                 image->assembly->aname.culture);
2586         }
2587
2588         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2589                 guchar pubtoken [9];
2590                 pubtoken [0] = 8;
2591                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2592                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2593         } else {
2594                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2595         }
2596         token <<= MONO_RESOLUTION_SCOPE_BITS;
2597         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2598         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2599         return token;
2600 }
2601
2602 static guint32
2603 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2604 {
2605         MONO_REQ_GC_NEUTRAL_MODE;
2606
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token;
2610         SigBuffer buf;
2611
2612         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2613                 return token;
2614
2615         sigbuffer_init (&buf, 32);
2616         switch (type->type) {
2617         case MONO_TYPE_FNPTR:
2618         case MONO_TYPE_PTR:
2619         case MONO_TYPE_SZARRAY:
2620         case MONO_TYPE_ARRAY:
2621         case MONO_TYPE_VAR:
2622         case MONO_TYPE_MVAR:
2623         case MONO_TYPE_GENERICINST:
2624                 encode_type (assembly, type, &buf);
2625                 break;
2626         case MONO_TYPE_CLASS:
2627         case MONO_TYPE_VALUETYPE: {
2628                 MonoClass *k = mono_class_from_mono_type (type);
2629                 if (!k || !k->generic_container) {
2630                         sigbuffer_free (&buf);
2631                         return 0;
2632                 }
2633                 encode_type (assembly, type, &buf);
2634                 break;
2635         }
2636         default:
2637                 sigbuffer_free (&buf);
2638                 return 0;
2639         }
2640
2641         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2642         if (assembly->save) {
2643                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2644                 alloc_table (table, table->rows + 1);
2645                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2646                 values [MONO_TYPESPEC_SIGNATURE] = token;
2647         }
2648         sigbuffer_free (&buf);
2649
2650         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2651         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2652         table->next_idx ++;
2653         return token;
2654 }
2655
2656 static guint32
2657 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2658 {
2659         MONO_REQ_GC_UNSAFE_MODE;
2660
2661         MonoDynamicTable *table;
2662         guint32 *values;
2663         guint32 token, scope, enclosing;
2664         MonoClass *klass;
2665
2666         /* if the type requires a typespec, we must try that first*/
2667         if (try_typespec && (token = create_typespec (assembly, type)))
2668                 return token;
2669         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2670         if (token)
2671                 return token;
2672         klass = mono_class_from_mono_type (type);
2673         if (!klass)
2674                 klass = mono_class_from_mono_type (type);
2675
2676         /*
2677          * If it's in the same module and not a generic type parameter:
2678          */
2679         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2680                         (type->type != MONO_TYPE_MVAR)) {
2681                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2682                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2683                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2684                 return token;
2685         }
2686
2687         if (klass->nested_in) {
2688                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2689                 /* get the typeref idx of the enclosing type */
2690                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2691                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2692         } else {
2693                 scope = resolution_scope_from_image (assembly, klass->image);
2694         }
2695         table = &assembly->tables [MONO_TABLE_TYPEREF];
2696         if (assembly->save) {
2697                 alloc_table (table, table->rows + 1);
2698                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2699                 values [MONO_TYPEREF_SCOPE] = scope;
2700                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2701                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2702         }
2703         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2704         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2705         table->next_idx ++;
2706         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2707         return token;
2708 }
2709
2710 /*
2711  * Despite the name, we handle also TypeSpec (with the above helper).
2712  */
2713 static guint32
2714 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2715 {
2716         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2717 }
2718
2719 #ifndef DISABLE_REFLECTION_EMIT
2720 static guint32
2721 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2722 {
2723         MONO_REQ_GC_NEUTRAL_MODE;
2724
2725         MonoDynamicTable *table;
2726         guint32 *values;
2727         guint32 token, pclass;
2728
2729         switch (parent & MONO_TYPEDEFORREF_MASK) {
2730         case MONO_TYPEDEFORREF_TYPEREF:
2731                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2732                 break;
2733         case MONO_TYPEDEFORREF_TYPESPEC:
2734                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2735                 break;
2736         case MONO_TYPEDEFORREF_TYPEDEF:
2737                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2738                 break;
2739         default:
2740                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2741                 return 0;
2742         }
2743         /* extract the index */
2744         parent >>= MONO_TYPEDEFORREF_BITS;
2745
2746         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2747
2748         if (assembly->save) {
2749                 alloc_table (table, table->rows + 1);
2750                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2751                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2752                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2753                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2754         }
2755
2756         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2757         table->next_idx ++;
2758
2759         return token;
2760 }
2761
2762 /*
2763  * Insert a memberef row into the metadata: the token that point to the memberref
2764  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2765  * mono_image_get_fieldref_token()).
2766  * The sig param is an index to an already built signature.
2767  */
2768 static guint32
2769 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2770 {
2771         MONO_REQ_GC_NEUTRAL_MODE;
2772
2773         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2774         return mono_image_add_memberef_row (assembly, parent, name, sig);
2775 }
2776
2777
2778 static guint32
2779 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2780 {
2781         MONO_REQ_GC_NEUTRAL_MODE;
2782
2783         guint32 token;
2784         MonoMethodSignature *sig;
2785         
2786         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2787
2788         if (create_typespec) {
2789                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2790                 if (token)
2791                         return token;
2792         } 
2793
2794         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795         if (token && !create_typespec)
2796                 return token;
2797
2798         g_assert (!method->is_inflated);
2799         if (!token) {
2800                 /*
2801                  * A methodref signature can't contain an unmanaged calling convention.
2802                  */
2803                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2804                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2805                         sig->call_convention = MONO_CALL_DEFAULT;
2806                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2807                         method->name,  method_encode_signature (assembly, sig));
2808                 g_free (sig);
2809                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2810         }
2811
2812         if (create_typespec) {
2813                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2814                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2815                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2816
2817                 if (assembly->save) {
2818                         guint32 *values;
2819
2820                         alloc_table (table, table->rows + 1);
2821                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2822                         values [MONO_METHODSPEC_METHOD] = token;
2823                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2824                 }
2825
2826                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2827                 table->next_idx ++;
2828                 /*methodspec and memberef tokens are diferent, */
2829                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2830                 return token;
2831         }
2832         return token;
2833 }
2834
2835 static guint32
2836 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2837 {
2838         guint32 token, parent, sig;
2839         ReflectionMethodBuilder rmb;
2840         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2841         
2842         mono_error_init (error);
2843         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2844         if (token)
2845                 return token;
2846
2847         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2848                 return 0;
2849
2850         /*
2851          * A methodref signature can't contain an unmanaged calling convention.
2852          * Since some flags are encoded as part of call_conv, we need to check against it.
2853         */
2854         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2855                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2856
2857         sig = method_builder_encode_signature (assembly, &rmb);
2858
2859         if (tb->generic_params)
2860                 parent = create_generic_typespec (assembly, tb);
2861         else
2862                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2863
2864         char *name = mono_string_to_utf8 (method->name);
2865
2866         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2867         g_free (name);
2868
2869         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2870
2871         return token;
2872 }
2873
2874 static guint32
2875 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2876                                      const gchar *name, guint32 sig)
2877 {
2878         MonoDynamicTable *table;
2879         guint32 token;
2880         guint32 *values;
2881         
2882         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2883
2884         if (assembly->save) {
2885                 alloc_table (table, table->rows + 1);
2886                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2887                 values [MONO_MEMBERREF_CLASS] = original;
2888                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2889                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2890         }
2891
2892         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2893         table->next_idx ++;
2894
2895         return token;
2896 }
2897
2898 static guint32
2899 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2900 {
2901         SigBuffer buf;
2902         int i;
2903         guint32 nparams = mono_array_length (mb->generic_params);
2904         guint32 idx;
2905
2906         if (!assembly->save)
2907                 return 0;
2908
2909         sigbuffer_init (&buf, 32);
2910
2911         sigbuffer_add_value (&buf, 0xa);
2912         sigbuffer_add_value (&buf, nparams);
2913
2914         for (i = 0; i < nparams; i++) {
2915                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2916                 sigbuffer_add_value (&buf, i);
2917         }
2918
2919         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2920         sigbuffer_free (&buf);
2921         return idx;
2922 }
2923
2924 static guint32
2925 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2926 {
2927         MonoDynamicTable *table;
2928         guint32 *values;
2929         guint32 token, mtoken = 0;
2930
2931         mono_error_init (error);
2932         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2933         if (token)
2934                 return token;
2935
2936         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2937
2938         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2939         if (!mono_error_ok (error))
2940                 return 0;
2941
2942         switch (mono_metadata_token_table (mtoken)) {
2943         case MONO_TABLE_MEMBERREF:
2944                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2945                 break;
2946         case MONO_TABLE_METHOD:
2947                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2948                 break;
2949         default:
2950                 g_assert_not_reached ();
2951         }
2952
2953         if (assembly->save) {
2954                 alloc_table (table, table->rows + 1);
2955                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2956                 values [MONO_METHODSPEC_METHOD] = mtoken;
2957                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2958         }
2959
2960         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2961         table->next_idx ++;
2962
2963         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2964         return token;
2965 }
2966
2967 static guint32
2968 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2969 {
2970         guint32 token;
2971
2972         mono_error_init (error);
2973
2974         if (mb->generic_params && create_methodspec) 
2975                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2976
2977         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2978         if (token)
2979                 return token;
2980
2981         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2982         if (!mono_error_ok (error))
2983                 return 0;
2984         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2985         return token;
2986 }
2987
2988 static guint32
2989 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2990 {
2991         guint32 token, parent, sig;
2992         ReflectionMethodBuilder rmb;
2993         char *name;
2994         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2995         
2996         mono_error_init (error);
2997         
2998         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2999         if (token)
3000                 return token;
3001
3002         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3003                 return 0;
3004
3005         if (tb->generic_params)
3006                 parent = create_generic_typespec (assembly, tb);
3007         else
3008                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3009         
3010         name = mono_string_to_utf8 (rmb.name);
3011         sig = method_builder_encode_signature (assembly, &rmb);
3012
3013         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3014
3015         g_free (name);
3016         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3017         return token;
3018 }
3019 #endif
3020
3021 static gboolean
3022 is_field_on_inst (MonoClassField *field)
3023 {
3024         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3025 }
3026
3027 /*
3028  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3029  */
3030 static MonoType*
3031 get_field_on_inst_generic_type (MonoClassField *field)
3032 {
3033         MonoClass *klass, *gtd;
3034         MonoDynamicGenericClass *dgclass;
3035         int field_index;
3036
3037         g_assert (is_field_on_inst (field));
3038
3039         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3040
3041         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3042                 field_index = field - dgclass->fields;
3043                 return dgclass->field_generic_types [field_index];              
3044         }
3045
3046         klass = field->parent;
3047         gtd = klass->generic_class->container_class;
3048
3049         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3050                 field_index = field - klass->fields;
3051                 return gtd->fields [field_index].type;
3052         }
3053
3054         g_assert_not_reached ();
3055         return 0;
3056 }
3057
3058 #ifndef DISABLE_REFLECTION_EMIT
3059 static guint32
3060 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3061 {
3062         MonoType *type;
3063         guint32 token;
3064
3065         g_assert (field);
3066         g_assert (field->parent);
3067
3068         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3069         if (token)
3070                 return token;
3071
3072         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3073                 int index = field - field->parent->fields;
3074                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3075         } else {
3076                 if (is_field_on_inst (field))
3077                         type = get_field_on_inst_generic_type (field);
3078                 else
3079                         type = mono_field_get_type (field);
3080         }
3081         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3082                                                                                         mono_field_get_name (field),
3083                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3084         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3085         return token;
3086 }
3087
3088 static guint32
3089 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3090 {
3091         guint32 token;
3092         MonoClass *klass;
3093         MonoGenericClass *gclass;
3094         MonoType *type;
3095         char *name;
3096
3097         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3098         if (token)
3099                 return token;
3100         if (is_sre_field_builder (mono_object_class (f->fb))) {
3101                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3102                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3103                 klass = mono_class_from_mono_type (type);
3104                 gclass = type->data.generic_class;
3105                 g_assert (gclass->is_dynamic);
3106
3107                 name = mono_string_to_utf8 (fb->name);
3108                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3109                                                                                                 field_encode_signature (assembly, fb));
3110                 g_free (name);          
3111         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3112                 guint32 sig;
3113                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3114
3115                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3116                 klass = mono_class_from_mono_type (type);
3117
3118                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3119                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3120         } else {
3121                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3122                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3123         }
3124
3125         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3126         return token;
3127 }
3128
3129 static guint32
3130 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3131 {
3132         guint32 sig, token;
3133         MonoClass *klass;
3134         MonoGenericClass *gclass;
3135         MonoType *type;
3136
3137         mono_error_init (error);
3138
3139         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3140
3141         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3142         if (token)
3143                 return token;
3144
3145         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3146                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3147                 ReflectionMethodBuilder rmb;
3148                 char *name;
3149
3150                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3151                 klass = mono_class_from_mono_type (type);
3152
3153                 gclass = type->data.generic_class;
3154                 g_assert (gclass->is_dynamic);
3155
3156                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3157                         return 0;
3158
3159                 name = mono_string_to_utf8 (rmb.name);
3160
3161                 sig = method_builder_encode_signature (assembly, &rmb);
3162
3163                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3164                 g_free (name);
3165         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3166                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3167
3168                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3169                 klass = mono_class_from_mono_type (type);
3170
3171                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3172                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3173         } else {
3174                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3175                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3176         }
3177
3178
3179         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3180         return token;
3181 }
3182
3183 static MonoMethod*
3184 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3185 {
3186         MonoClass *klass;
3187         MonoGenericContext tmp_context;
3188         MonoType **type_argv;
3189         MonoGenericInst *ginst;
3190         MonoMethod *method, *inflated;
3191         int count, i;
3192
3193         mono_error_init (error);
3194
3195         init_type_builder_generics ((MonoObject*)m->inst);
3196
3197         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3198         return_val_if_nok (error, NULL);
3199
3200         klass = method->klass;
3201
3202         if (m->method_args == NULL)
3203                 return method;
3204
3205         if (method->is_inflated)
3206                 method = ((MonoMethodInflated *) method)->declaring;
3207
3208         count = mono_array_length (m->method_args);
3209
3210         type_argv = g_new0 (MonoType *, count);
3211         for (i = 0; i < count; i++) {
3212                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3213                 type_argv [i] = mono_reflection_type_get_handle (garg);
3214         }
3215         ginst = mono_metadata_get_generic_inst (count, type_argv);
3216         g_free (type_argv);
3217
3218         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3219         tmp_context.method_inst = ginst;
3220
3221         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3222         mono_error_assert_ok (error);
3223         return inflated;
3224 }
3225
3226 static guint32
3227 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3228 {
3229         guint32 sig, token = 0;
3230         MonoType *type;
3231         MonoClass *klass;
3232
3233         mono_error_init (error);
3234
3235         if (m->method_args) {
3236                 MonoMethod *inflated;
3237
3238                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3239                 return_val_if_nok (error, 0);
3240
3241                 if (create_methodspec)
3242                         token = mono_image_get_methodspec_token (assembly, inflated);
3243                 else
3244                         token = mono_image_get_inflated_method_token (assembly, inflated);
3245                 return token;
3246         }
3247
3248         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3249         if (token)
3250                 return token;
3251
3252         if (is_sre_method_builder (mono_object_class (m->mb))) {
3253                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3254                 MonoGenericClass *gclass;
3255                 ReflectionMethodBuilder rmb;
3256                 char *name;
3257
3258                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3259                 klass = mono_class_from_mono_type (type);
3260                 gclass = type->data.generic_class;
3261                 g_assert (gclass->is_dynamic);
3262
3263                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3264                         return 0;
3265
3266                 name = mono_string_to_utf8 (rmb.name);
3267
3268                 sig = method_builder_encode_signature (assembly, &rmb);
3269
3270                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3271                 g_free (name);          
3272         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3273                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3274
3275                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3276                 klass = mono_class_from_mono_type (type);
3277
3278                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3279                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3280         } else {
3281                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3282                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3283         }
3284
3285         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3286         return token;
3287 }
3288
3289 static guint32
3290 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3291 {
3292         SigBuffer buf;
3293         int i;
3294         guint32 nparams = context->method_inst->type_argc;
3295         guint32 idx;
3296
3297         if (!assembly->save)
3298                 return 0;
3299
3300         sigbuffer_init (&buf, 32);
3301         /*
3302          * FIXME: vararg, explicit_this, differenc call_conv values...
3303          */
3304         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3305         sigbuffer_add_value (&buf, nparams);
3306
3307         for (i = 0; i < nparams; i++)
3308                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3309
3310         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3311         sigbuffer_free (&buf);
3312         return idx;
3313 }
3314
3315 static guint32
3316 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3317 {
3318         MonoDynamicTable *table;
3319         guint32 *values;
3320         guint32 token, mtoken = 0, sig;
3321         MonoMethodInflated *imethod;
3322         MonoMethod *declaring;
3323
3324         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3325
3326         g_assert (method->is_inflated);
3327         imethod = (MonoMethodInflated *) method;
3328         declaring = imethod->declaring;
3329
3330         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3331         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3332
3333         if (!mono_method_signature (declaring)->generic_param_count)
3334                 return mtoken;
3335
3336         switch (mono_metadata_token_table (mtoken)) {
3337         case MONO_TABLE_MEMBERREF:
3338                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3339                 break;
3340         case MONO_TABLE_METHOD:
3341                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3342                 break;
3343         default:
3344                 g_assert_not_reached ();
3345         }
3346
3347         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3348
3349         if (assembly->save) {
3350                 alloc_table (table, table->rows + 1);
3351                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3352                 values [MONO_METHODSPEC_METHOD] = mtoken;
3353                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3354         }
3355
3356         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3357         table->next_idx ++;
3358
3359         return token;
3360 }
3361
3362 static guint32
3363 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3364 {
3365         MonoMethodInflated *imethod;
3366         guint32 token;
3367         
3368         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3369         if (token)
3370                 return token;
3371
3372         g_assert (method->is_inflated);
3373         imethod = (MonoMethodInflated *) method;
3374
3375         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3376                 token = method_encode_methodspec (assembly, method);
3377         } else {
3378                 guint32 sig = method_encode_signature (
3379                         assembly, mono_method_signature (imethod->declaring));
3380                 token = mono_image_get_memberref_token (
3381                         assembly, &method->klass->byval_arg, method->name, sig);
3382         }
3383
3384         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3385         return token;
3386 }
3387
3388 static guint32
3389 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3390 {
3391         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3392         guint32 sig, token;
3393
3394         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3395         token = mono_image_get_memberref_token (
3396                 assembly, &m->klass->byval_arg, m->name, sig);
3397
3398         return token;
3399 }
3400
3401 static guint32
3402 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3403 {
3404         MonoDynamicTable *table;
3405         MonoClass *klass;
3406         MonoType *type;
3407         guint32 *values;
3408         guint32 token;
3409         SigBuffer buf;
3410         int count, i;
3411
3412         /*
3413          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3414          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3415          * Because of this, we must not insert it into the `typeref' hash table.
3416          */
3417         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3418         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3419         if (token)
3420                 return token;
3421
3422         sigbuffer_init (&buf, 32);
3423
3424         g_assert (tb->generic_params);
3425         klass = mono_class_from_mono_type (type);
3426
3427         if (tb->generic_container)
3428                 mono_reflection_create_generic_class (tb);
3429
3430         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3431         g_assert (klass->generic_container);
3432         sigbuffer_add_value (&buf, klass->byval_arg.type);
3433         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3434
3435         count = mono_array_length (tb->generic_params);
3436         sigbuffer_add_value (&buf, count);
3437         for (i = 0; i < count; i++) {
3438                 MonoReflectionGenericParam *gparam;
3439
3440                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3441
3442                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3443         }
3444
3445         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3446
3447         if (assembly->save) {
3448                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3449                 alloc_table (table, table->rows + 1);
3450                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3451                 values [MONO_TYPESPEC_SIGNATURE] = token;
3452         }
3453         sigbuffer_free (&buf);
3454
3455         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3456         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3457         table->next_idx ++;
3458         return token;
3459 }
3460
3461 /*
3462  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3463  */
3464 static MonoType*
3465 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3466 {
3467         int i, count, len, pos;
3468         MonoType *t;
3469
3470         count = 0;
3471         if (modreq)
3472                 count += mono_array_length (modreq);
3473         if (modopt)
3474                 count += mono_array_length (modopt);
3475
3476         if (count == 0)
3477                 return mono_metadata_type_dup (NULL, type);
3478
3479         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3480         t = (MonoType *)g_malloc (len);
3481         memcpy (t, type, MONO_SIZEOF_TYPE);
3482
3483         t->num_mods = count;
3484         pos = 0;
3485         if (modreq) {
3486                 for (i = 0; i < mono_array_length (modreq); ++i) {
3487                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3488                         t->modifiers [pos].required = 1;
3489                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3490                         pos ++;
3491                 }
3492         }
3493         if (modopt) {
3494                 for (i = 0; i < mono_array_length (modopt); ++i) {
3495                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3496                         t->modifiers [pos].required = 0;
3497                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3498                         pos ++;
3499                 }
3500         }
3501
3502         return t;
3503 }
3504
3505 static void
3506 init_type_builder_generics (MonoObject *type)
3507 {
3508         MonoReflectionTypeBuilder *tb;
3509
3510         if (!is_sre_type_builder(mono_object_class (type)))
3511                 return;
3512         tb = (MonoReflectionTypeBuilder *)type;
3513
3514         if (tb && tb->generic_container)
3515                 mono_reflection_create_generic_class (tb);
3516 }
3517
3518 static guint32
3519 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3520 {
3521         MonoDynamicTable *table;
3522         MonoType *custom = NULL, *type;
3523         guint32 *values;
3524         guint32 token, pclass, parent, sig;
3525         gchar *name;
3526
3527         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3528         if (token)
3529                 return token;
3530
3531         /* FIXME: is this call necessary? */
3532         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3533         name = mono_string_to_utf8 (fb->name);
3534
3535         /*FIXME this is one more layer of ugliness due how types are created.*/
3536         init_type_builder_generics (fb->type);
3537
3538         /* fb->type does not include the custom modifiers */
3539         /* FIXME: We should do this in one place when a fieldbuilder is created */
3540         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3541         if (fb->modreq || fb->modopt)
3542                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3543
3544         sig = fieldref_encode_signature (assembly, NULL, type);
3545         g_free (custom);
3546
3547         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3548         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3549         
3550         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3551         parent >>= MONO_TYPEDEFORREF_BITS;
3552
3553         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3554
3555         if (assembly->save) {
3556                 alloc_table (table, table->rows + 1);
3557                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3558                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3559                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3560                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3561         }
3562
3563         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3564         table->next_idx ++;
3565         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3566         g_free (name);
3567         return token;
3568 }
3569
3570 static guint32
3571 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3572 {
3573         SigBuffer buf;
3574         guint32 nargs;
3575         guint32 i, idx;
3576
3577         if (!assembly->save)
3578                 return 0;
3579
3580         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3581         g_assert (helper->type == 2);
3582
3583         if (helper->arguments)
3584                 nargs = mono_array_length (helper->arguments);
3585         else
3586                 nargs = 0;
3587
3588         sigbuffer_init (&buf, 32);
3589
3590         /* Encode calling convention */
3591         /* Change Any to Standard */
3592         if ((helper->call_conv & 0x03) == 0x03)
3593                 helper->call_conv = 0x01;
3594         /* explicit_this implies has_this */
3595         if (helper->call_conv & 0x40)
3596                 helper->call_conv &= 0x20;
3597
3598         if (helper->call_conv == 0) { /* Unmanaged */
3599                 idx = helper->unmanaged_call_conv - 1;
3600         } else {
3601                 /* Managed */
3602                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3603                 if (helper->call_conv & 0x02) /* varargs */
3604                         idx += 0x05;
3605         }
3606
3607         sigbuffer_add_byte (&buf, idx);
3608         sigbuffer_add_value (&buf, nargs);
3609         encode_reflection_type (assembly, helper->return_type, &buf);
3610         for (i = 0; i < nargs; ++i) {
3611                 MonoArray *modreqs = NULL;
3612                 MonoArray *modopts = NULL;
3613                 MonoReflectionType *pt;
3614
3615                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3616                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3617                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3618                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3619
3620                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3621                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3622                 encode_reflection_type (assembly, pt, &buf);
3623         }
3624         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3625         sigbuffer_free (&buf);
3626
3627         return idx;
3628 }
3629
3630 static guint32 
3631 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3632 {
3633         guint32 idx;
3634         MonoDynamicTable *table;
3635         guint32 *values;
3636
3637         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3638         idx = table->next_idx ++;
3639         table->rows ++;
3640         alloc_table (table, table->rows);
3641         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3642
3643         values [MONO_STAND_ALONE_SIGNATURE] =
3644                 mono_reflection_encode_sighelper (assembly, helper);
3645
3646         return idx;
3647 }
3648
3649 static int
3650 reflection_cc_to_file (int call_conv) {
3651         switch (call_conv & 0x3) {
3652         case 0:
3653         case 1: return MONO_CALL_DEFAULT;
3654         case 2: return MONO_CALL_VARARG;
3655         default:
3656                 g_assert_not_reached ();
3657         }
3658         return 0;
3659 }
3660 #endif /* !DISABLE_REFLECTION_EMIT */
3661
3662 typedef struct {
3663         MonoType *parent;
3664         MonoMethodSignature *sig;
3665         char *name;
3666         guint32 token;
3667 } ArrayMethod;
3668
3669 #ifndef DISABLE_REFLECTION_EMIT
3670 static guint32
3671 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3672 {
3673         guint32 nparams, i;
3674         GList *tmp;
3675         char *name;
3676         MonoMethodSignature *sig;
3677         ArrayMethod *am;
3678         MonoType *mtype;
3679
3680         name = mono_string_to_utf8 (m->name);
3681         nparams = mono_array_length (m->parameters);
3682         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3683         sig->hasthis = 1;
3684         sig->sentinelpos = -1;
3685         sig->call_convention = reflection_cc_to_file (m->call_conv);
3686         sig->param_count = nparams;
3687         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3688         mtype = mono_reflection_type_get_handle (m->parent);
3689         for (i = 0; i < nparams; ++i)
3690                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3691
3692         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3693                 am = (ArrayMethod *)tmp->data;
3694                 if (strcmp (name, am->name) == 0 && 
3695                                 mono_metadata_type_equal (am->parent, mtype) &&
3696                                 mono_metadata_signature_equal (am->sig, sig)) {
3697                         g_free (name);
3698                         g_free (sig);
3699                         m->table_idx = am->token & 0xffffff;
3700                         return am->token;
3701                 }
3702         }
3703         am = g_new0 (ArrayMethod, 1);
3704         am->name = name;
3705         am->sig = sig;
3706         am->parent = mtype;
3707         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3708                 method_encode_signature (assembly, sig));
3709         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3710         m->table_idx = am->token & 0xffffff;
3711         return am->token;
3712 }
3713
3714 /*
3715  * Insert into the metadata tables all the info about the TypeBuilder tb.
3716  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3717  */
3718 static gboolean
3719 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3720 {
3721         MonoDynamicTable *table;
3722         guint *values;
3723         int i, is_object = 0, is_system = 0;
3724         char *n;
3725
3726         mono_error_init (error);
3727
3728         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3729         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3730         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3731         n = mono_string_to_utf8 (tb->name);
3732         if (strcmp (n, "Object") == 0)
3733                 is_object++;
3734         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3735         g_free (n);
3736         n = mono_string_to_utf8 (tb->nspace);
3737         if (strcmp (n, "System") == 0)
3738                 is_system++;
3739         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3740         g_free (n);
3741         if (tb->parent && !(is_system && is_object) && 
3742                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3743                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3744         } else {
3745                 values [MONO_TYPEDEF_EXTENDS] = 0;
3746         }
3747         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3748         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3749
3750         /*
3751          * if we have explicitlayout or sequentiallayouts, output data in the
3752          * ClassLayout table.
3753          */
3754         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3755                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3756                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3757                 table->rows++;
3758                 alloc_table (table, table->rows);
3759                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3760                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3761                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3762                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3763         }
3764
3765         /* handle interfaces */
3766         if (tb->interfaces) {
3767                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3768                 i = table->rows;
3769                 table->rows += mono_array_length (tb->interfaces);
3770                 alloc_table (table, table->rows);
3771                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3772                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3773                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3774                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3775                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3776                         values += MONO_INTERFACEIMPL_SIZE;
3777                 }
3778         }
3779
3780         /* handle fields */
3781         if (tb->fields) {
3782                 table = &assembly->tables [MONO_TABLE_FIELD];
3783                 table->rows += tb->num_fields;
3784                 alloc_table (table, table->rows);
3785                 for (i = 0; i < tb->num_fields; ++i)
3786                         mono_image_get_field_info (
3787                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3788         }
3789
3790         /* handle constructors */
3791         if (tb->ctors) {
3792                 table = &assembly->tables [MONO_TABLE_METHOD];
3793                 table->rows += mono_array_length (tb->ctors);
3794                 alloc_table (table, table->rows);
3795                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3796                         if (!mono_image_get_ctor_info (domain,
3797                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3798                                                        assembly, error))
3799                                 return FALSE;
3800                 }
3801         }
3802
3803         /* handle methods */
3804         if (tb->methods) {
3805                 table = &assembly->tables [MONO_TABLE_METHOD];
3806                 table->rows += tb->num_methods;
3807                 alloc_table (table, table->rows);
3808                 for (i = 0; i < tb->num_methods; ++i) {
3809                         if (!mono_image_get_method_info (
3810                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3811                                 return FALSE;
3812                 }
3813         }
3814
3815         /* Do the same with properties etc.. */
3816         if (tb->events && mono_array_length (tb->events)) {
3817                 table = &assembly->tables [MONO_TABLE_EVENT];
3818                 table->rows += mono_array_length (tb->events);
3819                 alloc_table (table, table->rows);
3820                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3821                 table->rows ++;
3822                 alloc_table (table, table->rows);
3823                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3824                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3825                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3826                 for (i = 0; i < mono_array_length (tb->events); ++i)
3827                         mono_image_get_event_info (
3828                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3829         }
3830         if (tb->properties && mono_array_length (tb->properties)) {
3831                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3832                 table->rows += mono_array_length (tb->properties);
3833                 alloc_table (table, table->rows);
3834                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3835                 table->rows ++;
3836                 alloc_table (table, table->rows);
3837                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3838                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3839                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3840                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3841                         mono_image_get_property_info (
3842                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3843         }
3844
3845         /* handle generic parameters */
3846         if (tb->generic_params) {
3847                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3848                 table->rows += mono_array_length (tb->generic_params);
3849                 alloc_table (table, table->rows);
3850                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3851                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3852
3853                         mono_image_get_generic_param_info (
3854                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3855                 }
3856         }
3857
3858         mono_image_add_decl_security (assembly, 
3859                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3860
3861         if (tb->subtypes) {
3862                 MonoDynamicTable *ntable;
3863                 
3864                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3865                 ntable->rows += mono_array_length (tb->subtypes);
3866                 alloc_table (ntable, ntable->rows);
3867                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3868
3869                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3870                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3871
3872                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3873                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3874                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3875                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3876                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3877                                 ntable->next_idx, ntable->rows);*/
3878                         values += MONO_NESTED_CLASS_SIZE;
3879                         ntable->next_idx++;
3880                 }
3881         }
3882
3883         return TRUE;
3884 }
3885 #endif
3886
3887 static void
3888 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3889 {
3890         int i;
3891
3892         mono_ptr_array_append (*types, type);
3893
3894         if (!type->subtypes)
3895                 return;
3896
3897         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3898                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3899                 collect_types (types, subtype);
3900         }
3901 }
3902
3903 static gint
3904 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3905 {
3906         if ((*type1)->table_idx < (*type2)->table_idx)
3907                 return -1;
3908         else
3909                 if ((*type1)->table_idx > (*type2)->table_idx)
3910                         return 1;
3911         else
3912                 return 0;
3913 }
3914
3915 static gboolean
3916 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3917         int i;
3918
3919         mono_error_init (error);
3920         if (!pinfo)
3921                 return TRUE;
3922         for (i = 0; i < mono_array_length (pinfo); ++i) {
3923                 MonoReflectionParamBuilder *pb;
3924                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3925                 if (!pb)
3926                         continue;
3927                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3928                         return FALSE;
3929         }
3930
3931         return TRUE;
3932 }
3933
3934 static gboolean
3935 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3936         int i;
3937
3938         mono_error_init (error);
3939         
3940         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3941                 return FALSE;
3942         if (tb->fields) {
3943                 for (i = 0; i < tb->num_fields; ++i) {
3944                         MonoReflectionFieldBuilder* fb;
3945                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3946                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3947                                 return FALSE;
3948                 }
3949         }
3950         if (tb->events) {
3951                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3952                         MonoReflectionEventBuilder* eb;
3953                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3954                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3955                                 return FALSE;
3956                 }
3957         }
3958         if (tb->properties) {
3959                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3960                         MonoReflectionPropertyBuilder* pb;
3961                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3962                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3963                                 return FALSE;
3964                 }
3965         }
3966         if (tb->ctors) {
3967                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3968                         MonoReflectionCtorBuilder* cb;
3969                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3970                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3971                             !params_add_cattrs (assembly, cb->pinfo, error))
3972                                 return FALSE;
3973                 }
3974         }
3975
3976         if (tb->methods) {
3977                 for (i = 0; i < tb->num_methods; ++i) {
3978                         MonoReflectionMethodBuilder* mb;
3979                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3980                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3981                             !params_add_cattrs (assembly, mb->pinfo, error))
3982                                 return FALSE;
3983                 }
3984         }
3985
3986         if (tb->subtypes) {
3987                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3988                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3989                                 return FALSE;
3990                 }
3991         }
3992
3993         return TRUE;
3994 }
3995
3996 static gboolean
3997 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3998 {
3999         int i;
4000         
4001         mono_error_init (error);
4002
4003         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4004                 return FALSE;
4005
4006         if (moduleb->global_methods) {
4007                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4008                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4009                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4010                             !params_add_cattrs (assembly, mb->pinfo, error))
4011                                 return FALSE;
4012                 }
4013         }
4014
4015         if (moduleb->global_fields) {
4016                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4017                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4018                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4019                                 return FALSE;
4020                 }
4021         }
4022         
4023         if (moduleb->types) {
4024                 for (i = 0; i < moduleb->num_types; ++i) {
4025                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4026                                 return FALSE;
4027                 }
4028         }
4029
4030         return TRUE;
4031 }
4032
4033 static void
4034 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4035 {
4036         MonoDynamicTable *table;
4037         guint32 *values;
4038         char blob_size [6];
4039         guchar hash [20];
4040         char *b = blob_size;
4041         char *dir, *path;
4042
4043         table = &assembly->tables [MONO_TABLE_FILE];
4044         table->rows++;
4045         alloc_table (table, table->rows);
4046         values = table->values + table->next_idx * MONO_FILE_SIZE;
4047         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4048         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4049         if (image_is_dynamic (module->image)) {
4050                 /* This depends on the fact that the main module is emitted last */
4051                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4052                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4053         } else {
4054                 dir = NULL;
4055                 path = g_strdup (module->image->name);
4056         }
4057         mono_sha1_get_digest_from_file (path, hash);
4058         g_free (dir);
4059         g_free (path);
4060         mono_metadata_encode_value (20, b, &b);
4061         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4062         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4063         table->next_idx ++;
4064 }
4065
4066 static void
4067 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4068 {
4069         MonoDynamicTable *table;
4070         int i;
4071
4072         table = &assembly->tables [MONO_TABLE_MODULE];
4073         mb->table_idx = table->next_idx ++;
4074         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4075         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4076         i /= 16;
4077         ++i;
4078         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4079         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4080         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4081         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4082 }
4083
4084 static guint32
4085 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4086         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4087 {
4088         MonoDynamicTable *table;
4089         guint32 *values;
4090         guint32 visib, res;
4091
4092         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4093         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4094                 return 0;
4095
4096         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4097         table->rows++;
4098         alloc_table (table, table->rows);
4099         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4100
4101         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4102         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4103         if (klass->nested_in)
4104                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4105         else
4106                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4107         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4108         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4109
4110         res = table->next_idx;
4111
4112         table->next_idx ++;
4113
4114         /* Emit nested types */
4115         if (klass->ext && klass->ext->nested_classes) {
4116                 GList *tmp;
4117
4118                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4119                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4120         }
4121
4122         return res;
4123 }
4124
4125 static void
4126 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4127         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4128 {
4129         MonoClass *klass;
4130         guint32 idx, i;
4131
4132         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4133
4134         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4135
4136         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4137                                                                                                    parent_index, assembly);
4138
4139         /* 
4140          * Emit nested types
4141          * We need to do this ourselves since klass->nested_classes is not set up.
4142          */
4143         if (tb->subtypes) {
4144                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4145                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4146         }
4147 }
4148
4149 static void
4150 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4151         guint32 module_index, MonoDynamicImage *assembly)
4152 {
4153         MonoImage *image = module->image;
4154         MonoTableInfo  *t;
4155         guint32 i;
4156
4157         t = &image->tables [MONO_TABLE_TYPEDEF];
4158
4159         for (i = 0; i < t->rows; ++i) {
4160                 MonoError error;
4161                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4162                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4163
4164                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4165                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4166         }
4167 }
4168
4169 static void
4170 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4171 {
4172         MonoDynamicTable *table;
4173         guint32 *values;
4174         guint32 scope, scope_idx, impl, current_idx;
4175         gboolean forwarder = TRUE;
4176         gpointer iter = NULL;
4177         MonoClass *nested;
4178
4179         if (klass->nested_in) {
4180                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4181                 forwarder = FALSE;
4182         } else {
4183                 scope = resolution_scope_from_image (assembly, klass->image);
4184                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4185                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4186                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4187         }
4188
4189         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4190
4191         table->rows++;
4192         alloc_table (table, table->rows);
4193         current_idx = table->next_idx;
4194         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4195
4196         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4197         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4198         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4199         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4200         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4201
4202         table->next_idx++;
4203
4204         while ((nested = mono_class_get_nested_types (klass, &iter)))
4205                 add_exported_type (assemblyb, assembly, nested, current_idx);
4206 }
4207
4208 static void
4209 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4210 {
4211         MonoClass *klass;
4212         int i;
4213
4214         if (!assemblyb->type_forwarders)
4215                 return;
4216
4217         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4218                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4219                 MonoType *type;
4220                 if (!t)
4221                         continue;
4222
4223                 type = mono_reflection_type_get_handle (t);
4224                 g_assert (type);
4225
4226                 klass = mono_class_from_mono_type (type);
4227
4228                 add_exported_type (assemblyb, assembly, klass, 0);
4229         }
4230 }
4231
4232 #define align_pointer(base,p)\
4233         do {\
4234                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4235                 if (__diff & 3)\
4236                         (p) += 4 - (__diff & 3);\
4237         } while (0)
4238
4239 static int
4240 compare_constants (const void *a, const void *b)
4241 {
4242         const guint32 *a_values = (const guint32 *)a;
4243         const guint32 *b_values = (const guint32 *)b;
4244         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4245 }
4246
4247 static int
4248 compare_semantics (const void *a, const void *b)
4249 {
4250         const guint32 *a_values = (const guint32 *)a;
4251         const guint32 *b_values = (const guint32 *)b;
4252         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4253         if (assoc)
4254                 return assoc;
4255         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4256 }
4257
4258 static int
4259 compare_custom_attrs (const void *a, const void *b)
4260 {
4261         const guint32 *a_values = (const guint32 *)a;
4262         const guint32 *b_values = (const guint32 *)b;
4263
4264         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4265 }
4266
4267 static int
4268 compare_field_marshal (const void *a, const void *b)
4269 {
4270         const guint32 *a_values = (const guint32 *)a;
4271         const guint32 *b_values = (const guint32 *)b;
4272
4273         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4274 }
4275
4276 static int
4277 compare_nested (const void *a, const void *b)
4278 {
4279         const guint32 *a_values = (const guint32 *)a;
4280         const guint32 *b_values = (const guint32 *)b;
4281
4282         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4283 }
4284
4285 static int
4286 compare_genericparam (const void *a, const void *b)
4287 {
4288         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4289         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4290
4291         if ((*b_entry)->owner == (*a_entry)->owner)
4292                 return 
4293                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4294                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4295         else
4296                 return (*a_entry)->owner - (*b_entry)->owner;
4297 }
4298
4299 static int
4300 compare_declsecurity_attrs (const void *a, const void *b)
4301 {
4302         const guint32 *a_values = (const guint32 *)a;
4303         const guint32 *b_values = (const guint32 *)b;
4304
4305         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4306 }
4307
4308 static int
4309 compare_interface_impl (const void *a, const void *b)
4310 {
4311         const guint32 *a_values = (const guint32 *)a;
4312         const guint32 *b_values = (const guint32 *)b;
4313
4314         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4315         if (klass)
4316                 return klass;
4317
4318         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4319 }
4320
4321 static void
4322 pad_heap (MonoDynamicStream *sh)
4323 {
4324         if (sh->index & 3) {
4325                 int sz = 4 - (sh->index & 3);
4326                 memset (sh->data + sh->index, 0, sz);
4327                 sh->index += sz;
4328         }
4329 }
4330
4331 struct StreamDesc {
4332         const char *name;
4333         MonoDynamicStream *stream;
4334 };
4335
4336 /*
4337  * build_compressed_metadata() fills in the blob of data that represents the 
4338  * raw metadata as it will be saved in the PE file. The five streams are output 
4339  * and the metadata tables are comnpressed from the guint32 array representation, 
4340  * to the compressed on-disk format.
4341  */
4342 static gboolean
4343 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4344 {
4345         MonoDynamicTable *table;
4346         int i;
4347         guint64 valid_mask = 0;
4348         guint64 sorted_mask;
4349         guint32 heapt_size = 0;
4350         guint32 meta_size = 256; /* allow for header and other stuff */
4351         guint32 table_offset;
4352         guint32 ntables = 0;
4353         guint64 *int64val;
4354         guint32 *int32val;
4355         guint16 *int16val;
4356         MonoImage *meta;
4357         unsigned char *p;
4358         struct StreamDesc stream_desc [5];
4359
4360         mono_error_init (error);
4361
4362         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4363         for (i = 0; i < assembly->gen_params->len; i++) {
4364                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4365                 if (!write_generic_param_entry (assembly, entry, error))
4366                         return FALSE;
4367         }
4368
4369         stream_desc [0].name  = "#~";
4370         stream_desc [0].stream = &assembly->tstream;
4371         stream_desc [1].name  = "#Strings";
4372         stream_desc [1].stream = &assembly->sheap;
4373         stream_desc [2].name  = "#US";
4374         stream_desc [2].stream = &assembly->us;
4375         stream_desc [3].name  = "#Blob";
4376         stream_desc [3].stream = &assembly->blob;
4377         stream_desc [4].name  = "#GUID";
4378         stream_desc [4].stream = &assembly->guid;
4379         
4380         /* tables that are sorted */
4381         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4382                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4383                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4384                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4385                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4386                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4387                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4388         
4389         /* Compute table sizes */
4390         /* the MonoImage has already been created in mono_image_basic_init() */
4391         meta = &assembly->image;
4392
4393         /* sizes should be multiple of 4 */
4394         pad_heap (&assembly->blob);
4395         pad_heap (&assembly->guid);
4396         pad_heap (&assembly->sheap);
4397         pad_heap (&assembly->us);
4398
4399         /* Setup the info used by compute_sizes () */
4400         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4401         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4402         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4403
4404         meta_size += assembly->blob.index;
4405         meta_size += assembly->guid.index;
4406         meta_size += assembly->sheap.index;
4407         meta_size += assembly->us.index;
4408
4409         for (i=0; i < MONO_TABLE_NUM; ++i)
4410                 meta->tables [i].rows = assembly->tables [i].rows;
4411         
4412         for (i = 0; i < MONO_TABLE_NUM; i++){
4413                 if (meta->tables [i].rows == 0)
4414                         continue;
4415                 valid_mask |= (guint64)1 << i;
4416                 ntables ++;
4417                 meta->tables [i].row_size = mono_metadata_compute_size (
4418                         meta, i, &meta->tables [i].size_bitfield);
4419                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4420         }
4421         heapt_size += 24; /* #~ header size */
4422         heapt_size += ntables * 4;
4423         /* make multiple of 4 */
4424         heapt_size += 3;
4425         heapt_size &= ~3;
4426         meta_size += heapt_size;
4427         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4428         p = (unsigned char*)meta->raw_metadata;
4429         /* the metadata signature */
4430         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4431         /* version numbers and 4 bytes reserved */
4432         int16val = (guint16*)p;
4433         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4434         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4435         p += 8;
4436         /* version string */
4437         int32val = (guint32*)p;
4438         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4439         p += 4;
4440         memcpy (p, meta->version, strlen (meta->version));
4441         p += GUINT32_FROM_LE (*int32val);
4442         align_pointer (meta->raw_metadata, p);
4443         int16val = (guint16*)p;
4444         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4445         *int16val = GUINT16_TO_LE (5); /* number of streams */
4446         p += 4;
4447
4448         /*
4449          * write the stream info.
4450          */
4451         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4452         table_offset += 3; table_offset &= ~3;
4453
4454         assembly->tstream.index = heapt_size;
4455         for (i = 0; i < 5; ++i) {
4456                 int32val = (guint32*)p;
4457                 stream_desc [i].stream->offset = table_offset;
4458                 *int32val++ = GUINT32_TO_LE (table_offset);
4459                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4460                 table_offset += GUINT32_FROM_LE (*int32val);
4461                 table_offset += 3; table_offset &= ~3;
4462                 p += 8;
4463                 strcpy ((char*)p, stream_desc [i].name);
4464                 p += strlen (stream_desc [i].name) + 1;
4465                 align_pointer (meta->raw_metadata, p);
4466         }
4467         /* 
4468          * now copy the data, the table stream header and contents goes first.
4469          */
4470         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4471         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4472         int32val = (guint32*)p;
4473         *int32val = GUINT32_TO_LE (0); /* reserved */
4474         p += 4;
4475
4476         *p++ = 2; /* version */
4477         *p++ = 0;
4478
4479         if (meta->idx_string_wide)
4480                 *p |= 0x01;
4481         if (meta->idx_guid_wide)
4482                 *p |= 0x02;
4483         if (meta->idx_blob_wide)
4484                 *p |= 0x04;
4485         ++p;
4486         *p++ = 1; /* reserved */
4487         int64val = (guint64*)p;
4488         *int64val++ = GUINT64_TO_LE (valid_mask);
4489         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4490         p += 16;
4491         int32val = (guint32*)p;
4492         for (i = 0; i < MONO_TABLE_NUM; i++){
4493                 if (meta->tables [i].rows == 0)
4494                         continue;
4495                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4496         }
4497         p = (unsigned char*)int32val;
4498
4499         /* sort the tables that still need sorting */
4500         table = &assembly->tables [MONO_TABLE_CONSTANT];
4501         if (table->rows)
4502                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4503         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4504         if (table->rows)
4505                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4506         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4507         if (table->rows)
4508                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4509         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4510         if (table->rows)
4511                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4512         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4513         if (table->rows)
4514                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4515         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4516         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4517         if (table->rows)
4518                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4519         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4520         if (table->rows)
4521                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4522
4523         /* compress the tables */
4524         for (i = 0; i < MONO_TABLE_NUM; i++){
4525                 int row, col;
4526                 guint32 *values;
4527                 guint32 bitfield = meta->tables [i].size_bitfield;
4528                 if (!meta->tables [i].rows)
4529                         continue;
4530                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4531                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4532                 meta->tables [i].base = (char*)p;
4533                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4534                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4535                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4536                                 switch (mono_metadata_table_size (bitfield, col)) {
4537                                 case 1:
4538                                         *p++ = values [col];
4539                                         break;
4540                                 case 2:
4541                                         *p++ = values [col] & 0xff;
4542                                         *p++ = (values [col] >> 8) & 0xff;
4543                                         break;
4544                                 case 4:
4545                                         *p++ = values [col] & 0xff;
4546                                         *p++ = (values [col] >> 8) & 0xff;
4547                                         *p++ = (values [col] >> 16) & 0xff;
4548                                         *p++ = (values [col] >> 24) & 0xff;
4549                                         break;
4550                                 default:
4551                                         g_assert_not_reached ();
4552                                 }
4553                         }
4554                 }
4555                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4556         }
4557         
4558         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4559         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4560         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4561         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4562         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4563
4564         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4565
4566         return TRUE;
4567 }
4568
4569 /*
4570  * Some tables in metadata need to be sorted according to some criteria, but
4571  * when methods and fields are first created with reflection, they may be assigned a token
4572  * that doesn't correspond to the final token they will get assigned after the sorting.
4573  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4574  * with the reflection objects that represent them. Once all the tables are set up, the 
4575  * reflection objects will contains the correct table index. fixup_method() will fixup the
4576  * tokens for the method with ILGenerator @ilgen.
4577  */
4578 static void
4579 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4580 {
4581         guint32 code_idx = GPOINTER_TO_UINT (value);
4582         MonoReflectionILTokenInfo *iltoken;
4583         MonoReflectionFieldBuilder *field;
4584         MonoReflectionCtorBuilder *ctor;
4585         MonoReflectionMethodBuilder *method;
4586         MonoReflectionTypeBuilder *tb;
4587         MonoReflectionArrayMethod *am;
4588         guint32 i, idx = 0;
4589         unsigned char *target;
4590
4591         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4592                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4593                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4594                 switch (target [3]) {
4595                 case MONO_TABLE_FIELD:
4596                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4597                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4598                                 idx = field->table_idx;
4599                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4600                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4601                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4602                         } else {
4603                                 g_assert_not_reached ();
4604                         }
4605                         break;
4606                 case MONO_TABLE_METHOD:
4607                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4608                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4609                                 idx = method->table_idx;
4610                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4611                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4612                                 idx = ctor->table_idx;
4613                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4614                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4615                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4617                         } else {
4618                                 g_assert_not_reached ();
4619                         }
4620                         break;
4621                 case MONO_TABLE_TYPEDEF:
4622                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4623                                 g_assert_not_reached ();
4624                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4625                         idx = tb->table_idx;
4626                         break;
4627                 case MONO_TABLE_MEMBERREF:
4628                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4629                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4630                                 idx = am->table_idx;
4631                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4632                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4633                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4634                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4635                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4637                                 continue;
4638                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4639                                 continue;
4640                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4641                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4642                                 g_assert (is_field_on_inst (f));
4643                                 continue;
4644                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4645                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4646                                 continue;
4647                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4648                                 continue;
4649                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4650                                 continue;
4651                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4652                                 continue;
4653                         } else {
4654                                 g_assert_not_reached ();
4655                         }
4656                         break;
4657                 case MONO_TABLE_METHODSPEC:
4658                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4659                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4660                                 g_assert (mono_method_signature (m)->generic_param_count);
4661                                 continue;
4662                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4663                                 continue;
4664                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4665                                 continue;
4666                         } else {
4667                                 g_assert_not_reached ();
4668                         }
4669                         break;
4670                 default:
4671                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4672                 }
4673                 target [0] = idx & 0xff;
4674                 target [1] = (idx >> 8) & 0xff;
4675                 target [2] = (idx >> 16) & 0xff;
4676         }
4677 }
4678
4679 /*
4680  * fixup_cattrs:
4681  *
4682  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4683  * value is not known when the table is emitted.
4684  */
4685 static void
4686 fixup_cattrs (MonoDynamicImage *assembly)
4687 {
4688         MonoDynamicTable *table;
4689         guint32 *values;
4690         guint32 type, i, idx, token;
4691         MonoObject *ctor;
4692
4693         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4694
4695         for (i = 0; i < table->rows; ++i) {
4696                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4697
4698                 type = values [MONO_CUSTOM_ATTR_TYPE];
4699                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4700                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4701                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4702                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4703                         g_assert (ctor);
4704
4705                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4706                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4707                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4708                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4709                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4710                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4711                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4712                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4713                         }
4714                 }
4715         }
4716 }
4717
4718 static void
4719 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4720 {
4721         MonoDynamicTable *table;
4722         guint32 *values;
4723
4724         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4725         table->rows++;
4726         alloc_table (table, table->rows);
4727         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4728         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4729         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4730         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4731         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4732         table->next_idx++;
4733 }
4734
4735 static void
4736 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4737 {
4738         MonoDynamicTable *table;
4739         guint32 *values;
4740         char blob_size [6];
4741         guchar hash [20];
4742         char *b = blob_size;
4743         char *name, *sname;
4744         guint32 idx, offset;
4745
4746         if (rsrc->filename) {
4747                 name = mono_string_to_utf8 (rsrc->filename);
4748                 sname = g_path_get_basename (name);
4749         
4750                 table = &assembly->tables [MONO_TABLE_FILE];
4751                 table->rows++;
4752                 alloc_table (table, table->rows);
4753                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4754                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4755                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4756                 g_free (sname);
4757
4758                 mono_sha1_get_digest_from_file (name, hash);
4759                 mono_metadata_encode_value (20, b, &b);
4760                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4761                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4762                 g_free (name);
4763                 idx = table->next_idx++;
4764                 rsrc->offset = 0;
4765                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4766         } else {
4767                 char sizebuf [4];
4768                 char *data;
4769                 guint len;
4770                 if (rsrc->data) {
4771                         data = mono_array_addr (rsrc->data, char, 0);
4772                         len = mono_array_length (rsrc->data);
4773                 } else {
4774                         data = NULL;
4775                         len = 0;
4776                 }
4777                 offset = len;
4778                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4779                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4780                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4781                 mono_image_add_stream_data (&assembly->resources, data, len);
4782
4783                 if (!mb->is_main)
4784                         /* 
4785                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4786                          * the main module, but that needs to reference the FILE table
4787                          * which isn't emitted yet.
4788                          */
4789                         return;
4790                 else
4791                         idx = 0;
4792         }
4793
4794         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4795 }
4796
4797 static void
4798 set_version_from_string (MonoString *version, guint32 *values)
4799 {
4800         gchar *ver, *p, *str;
4801         guint32 i;
4802         
4803         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4804         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4805         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4806         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4807         if (!version)
4808                 return;
4809         ver = str = mono_string_to_utf8 (version);
4810         for (i = 0; i < 4; ++i) {
4811                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4812                 switch (*p) {
4813                 case '.':
4814                         p++;
4815                         break;
4816                 case '*':
4817                         /* handle Revision and Build */
4818                         p++;
4819                         break;
4820                 }
4821                 ver = p;
4822         }
4823         g_free (str);
4824 }
4825
4826 static guint32
4827 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4828         gsize len;
4829         guint32 token = 0;
4830         char blob_size [6];
4831         char *b = blob_size;
4832
4833         if (!pkey)
4834                 return token;
4835
4836         len = mono_array_length (pkey);
4837         mono_metadata_encode_value (len, b, &b);
4838         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4839         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4840
4841         assembly->public_key = (guint8 *)g_malloc (len);
4842         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4843         assembly->public_key_len = len;
4844
4845         /* Special case: check for ECMA key (16 bytes) */
4846         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4847                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4848                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4849         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4850                 /* minimum key size (in 2.0) is 384 bits */
4851                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4852         } else {
4853                 /* FIXME - verifier */
4854                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4855                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4856         }
4857         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4858
4859         return token;
4860 }
4861
4862 static void
4863 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4864 {
4865         MonoDynamicTable *table;
4866         MonoDynamicImage *assembly;
4867         MonoReflectionAssemblyBuilder *assemblyb;
4868         MonoDomain *domain;
4869         guint32 *values;
4870         int i;
4871         guint32 module_index;
4872
4873         assemblyb = moduleb->assemblyb;
4874         assembly = moduleb->dynamic_image;
4875         domain = mono_object_domain (assemblyb);
4876
4877         /* Emit ASSEMBLY table */
4878         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4879         alloc_table (table, 1);
4880         values = table->values + MONO_ASSEMBLY_SIZE;
4881         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4882         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4883         if (assemblyb->culture) {
4884                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4885         } else {
4886                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4887         }
4888         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4889         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4890         set_version_from_string (assemblyb->version, values);
4891
4892         /* Emit FILE + EXPORTED_TYPE table */
4893         module_index = 0;
4894         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4895                 int j;
4896                 MonoReflectionModuleBuilder *file_module = 
4897                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4898                 if (file_module != moduleb) {
4899                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4900                         module_index ++;
4901                         if (file_module->types) {
4902                                 for (j = 0; j < file_module->num_types; ++j) {
4903                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4904                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4905                                 }
4906                         }
4907                 }
4908         }
4909         if (assemblyb->loaded_modules) {
4910                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4911                         MonoReflectionModule *file_module = 
4912                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4913                         mono_image_fill_file_table (domain, file_module, assembly);
4914                         module_index ++;
4915                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4916                 }
4917         }
4918         if (assemblyb->type_forwarders)
4919                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4920
4921         /* Emit MANIFESTRESOURCE table */
4922         module_index = 0;
4923         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4924                 int j;
4925                 MonoReflectionModuleBuilder *file_module = 
4926                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4927                 /* The table for the main module is emitted later */
4928                 if (file_module != moduleb) {
4929                         module_index ++;
4930                         if (file_module->resources) {
4931                                 int len = mono_array_length (file_module->resources);
4932                                 for (j = 0; j < len; ++j) {
4933                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4934                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4935                                 }
4936                         }
4937                 }
4938         }               
4939 }
4940
4941 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4942
4943 /*
4944  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4945  * for the modulebuilder @moduleb.
4946  * At the end of the process, method and field tokens are fixed up and the 
4947  * on-disk compressed metadata representation is created.
4948  * Return TRUE on success, or FALSE on failure and sets @error
4949  */
4950 gboolean
4951 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4952 {
4953         MonoDynamicTable *table;
4954         MonoDynamicImage *assembly;
4955         MonoReflectionAssemblyBuilder *assemblyb;
4956         MonoDomain *domain;
4957         MonoPtrArray types;
4958         guint32 *values;
4959         int i, j;
4960
4961         mono_error_init (error);
4962
4963         assemblyb = moduleb->assemblyb;
4964         assembly = moduleb->dynamic_image;
4965         domain = mono_object_domain (assemblyb);
4966
4967         if (assembly->text_rva)
4968                 return TRUE;
4969
4970         assembly->text_rva = START_TEXT_RVA;
4971
4972         if (moduleb->is_main) {
4973                 mono_image_emit_manifest (moduleb);
4974         }
4975
4976         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4977         table->rows = 1; /* .<Module> */
4978         table->next_idx++;
4979         alloc_table (table, table->rows);
4980         /*
4981          * Set the first entry.
4982          */
4983         values = table->values + table->columns;
4984         values [MONO_TYPEDEF_FLAGS] = 0;
4985         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4986         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4987         values [MONO_TYPEDEF_EXTENDS] = 0;
4988         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4989         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4990
4991         /* 
4992          * handle global methods 
4993          * FIXME: test what to do when global methods are defined in multiple modules.
4994          */
4995         if (moduleb->global_methods) {
4996                 table = &assembly->tables [MONO_TABLE_METHOD];
4997                 table->rows += mono_array_length (moduleb->global_methods);
4998                 alloc_table (table, table->rows);
4999                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5000                         if (!mono_image_get_method_info (
5001                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5002                                 goto leave;
5003                 }
5004         }
5005         if (moduleb->global_fields) {
5006                 table = &assembly->tables [MONO_TABLE_FIELD];
5007                 table->rows += mono_array_length (moduleb->global_fields);
5008                 alloc_table (table, table->rows);
5009                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5010                         mono_image_get_field_info (
5011                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5012         }
5013
5014         table = &assembly->tables [MONO_TABLE_MODULE];
5015         alloc_table (table, 1);
5016         mono_image_fill_module_table (domain, moduleb, assembly);
5017
5018         /* Collect all types into a list sorted by their table_idx */
5019         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5020
5021         if (moduleb->types)
5022                 for (i = 0; i < moduleb->num_types; ++i) {
5023                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5024                         collect_types (&types, type);
5025                 }
5026
5027         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5028         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5029         table->rows += mono_ptr_array_size (types);
5030         alloc_table (table, table->rows);
5031
5032         /*
5033          * Emit type names + namespaces at one place inside the string heap,
5034          * so load_class_names () needs to touch fewer pages.
5035          */
5036         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5037                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5038                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5039         }
5040         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5041                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5042                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5043         }
5044
5045         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5046                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5047                 if (!mono_image_get_type_info (domain, type, assembly, error))
5048                         goto leave_types;
5049         }
5050
5051         /* 
5052          * table->rows is already set above and in mono_image_fill_module_table.
5053          */
5054         /* add all the custom attributes at the end, once all the indexes are stable */
5055         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5056                 goto leave_types;
5057
5058         /* CAS assembly permissions */
5059         if (assemblyb->permissions_minimum)
5060                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5061         if (assemblyb->permissions_optional)
5062                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5063         if (assemblyb->permissions_refused)
5064                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5065
5066         if (!module_add_cattrs (assembly, moduleb, error))
5067                 goto leave_types;
5068
5069         /* fixup tokens */
5070         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5071
5072         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5073          * the final tokens and don't need another fixup pass. */
5074
5075         if (moduleb->global_methods) {
5076                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5077                         MonoReflectionMethodBuilder *mb = mono_array_get (
5078                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5079                         if (!mono_image_add_methodimpl (assembly, mb, error))
5080                                 goto leave_types;
5081                 }
5082         }
5083
5084         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5085                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5086                 if (type->methods) {
5087                         for (j = 0; j < type->num_methods; ++j) {
5088                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5089                                         type->methods, MonoReflectionMethodBuilder*, j);
5090
5091                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5092                                         goto leave_types;
5093                         }
5094                 }
5095         }
5096
5097         fixup_cattrs (assembly);
5098
5099 leave_types:
5100         mono_ptr_array_destroy (types);
5101 leave:
5102
5103         return mono_error_ok (error);
5104 }
5105
5106 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5107
5108 gboolean
5109 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5110 {
5111         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5112 }
5113
5114 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5115
5116
5117 typedef struct {
5118         guint32 import_lookup_table;
5119         guint32 timestamp;
5120         guint32 forwarder;
5121         guint32 name_rva;
5122         guint32 import_address_table_rva;
5123 } MonoIDT;
5124
5125 typedef struct {
5126         guint32 name_rva;
5127         guint32 flags;
5128 } MonoILT;
5129
5130 #ifndef DISABLE_REFLECTION_EMIT
5131
5132 /*
5133  * mono_image_insert_string:
5134  * @module: module builder object
5135  * @str: a string
5136  *
5137  * Insert @str into the user string stream of @module.
5138  */
5139 guint32
5140 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5141 {
5142         MonoDynamicImage *assembly;
5143         guint32 idx;
5144         char buf [16];
5145         char *b = buf;
5146         
5147         if (!module->dynamic_image)
5148                 mono_image_module_basic_init (module);
5149
5150         assembly = module->dynamic_image;
5151         
5152         if (assembly->save) {
5153                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5154                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5155 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5156         {
5157                 char *swapped = g_malloc (2 * mono_string_length (str));
5158                 const char *p = (const char*)mono_string_chars (str);
5159
5160                 swap_with_size (swapped, p, 2, mono_string_length (str));
5161                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5162                 g_free (swapped);
5163         }
5164 #else
5165                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5166 #endif
5167                 mono_image_add_stream_data (&assembly->us, "", 1);
5168         } else {
5169                 idx = assembly->us.index ++;
5170         }
5171
5172         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5173
5174         return MONO_TOKEN_STRING | idx;
5175 }
5176
5177 guint32
5178 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5179 {
5180         MonoClass *klass;
5181         guint32 token = 0;
5182         MonoMethodSignature *sig;
5183
5184         mono_error_init (error);
5185
5186         klass = obj->vtable->klass;
5187         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5188                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5189                 MonoMethodSignature *old;
5190                 guint32 sig_token, parent;
5191                 int nargs, i;
5192
5193                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5194
5195                 nargs = mono_array_length (opt_param_types);
5196                 old = mono_method_signature (method);
5197                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5198
5199                 sig->hasthis = old->hasthis;
5200                 sig->explicit_this = old->explicit_this;
5201                 sig->call_convention = old->call_convention;
5202                 sig->generic_param_count = old->generic_param_count;
5203                 sig->param_count = old->param_count + nargs;
5204                 sig->sentinelpos = old->param_count;
5205                 sig->ret = old->ret;
5206
5207                 for (i = 0; i < old->param_count; i++)
5208                         sig->params [i] = old->params [i];
5209
5210                 for (i = 0; i < nargs; i++) {
5211                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5212                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5213                 }
5214
5215                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5216                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5217                 parent >>= MONO_TYPEDEFORREF_BITS;
5218
5219                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5220                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5221
5222                 sig_token = method_encode_signature (assembly, sig);
5223                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5224         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5225                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5226                 ReflectionMethodBuilder rmb;
5227                 guint32 parent, sig_token;
5228                 int nopt_args, nparams, ngparams, i;
5229
5230                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5231                         goto fail;
5232                 
5233                 rmb.opt_types = opt_param_types;
5234                 nopt_args = mono_array_length (opt_param_types);
5235
5236                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5237                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5238                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5239
5240                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5241                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5242                 sig->call_convention = rmb.call_conv;
5243                 sig->generic_param_count = ngparams;
5244                 sig->param_count = nparams + nopt_args;
5245                 sig->sentinelpos = nparams;
5246                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5247
5248                 for (i = 0; i < nparams; i++) {
5249                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5250                         sig->params [i] = mono_reflection_type_get_handle (rt);
5251                 }
5252
5253                 for (i = 0; i < nopt_args; i++) {
5254                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5255                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5256                 }
5257
5258                 sig_token = method_builder_encode_signature (assembly, &rmb);
5259
5260                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5261                 if (!mono_error_ok (error))
5262                         goto fail;
5263                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5264
5265                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5266                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5267
5268                 char *name = mono_string_to_utf8 (rmb.name);
5269                 token = mono_image_get_varargs_method_token (
5270                         assembly, parent, name, sig_token);
5271                 g_free (name);
5272         } else {
5273                 g_error ("requested method token for %s\n", klass->name);
5274         }
5275
5276         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5277         register_dyn_token (assembly, token, obj);
5278         return token;
5279 fail:
5280         g_assert (!mono_error_ok (error));
5281         return 0;
5282 }
5283
5284 /*
5285  * mono_image_create_token:
5286  * @assembly: a dynamic assembly
5287  * @obj:
5288  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5289  *
5290  * Get a token to insert in the IL code stream for the given MemberInfo.
5291  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5292  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5293  * entry.
5294  */
5295 guint32
5296 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5297                          gboolean create_open_instance, gboolean register_token,
5298                          MonoError *error)
5299 {
5300         MonoClass *klass;
5301         guint32 token = 0;
5302
5303         mono_error_init (error);
5304
5305         klass = obj->vtable->klass;
5306
5307         /* Check for user defined reflection objects */
5308         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5309         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5310                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5311                 return 0;
5312         }
5313
5314         if (strcmp (klass->name, "MethodBuilder") == 0) {
5315                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5316                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5317
5318                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5319                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5320                 else {
5321                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5322                         if (!mono_error_ok (error))
5323                                 return 0;
5324                 }
5325                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5326         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5327                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5328                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5329
5330                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5331                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5332                 else {
5333                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5334                         if (!mono_error_ok (error))
5335                                 return 0;
5336                 }
5337                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5338         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5339                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5340                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5341                 if (tb->generic_params) {
5342                         token = mono_image_get_generic_field_token (assembly, fb);
5343                 } else {
5344                         if (tb->module->dynamic_image == assembly) {
5345                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5346                         } else {
5347                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5348                         }
5349                 }
5350         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5351                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5352                 if (create_open_instance && tb->generic_params) {
5353                         MonoType *type;
5354                         init_type_builder_generics (obj);
5355                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5356                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5357                         token = mono_metadata_token_from_dor (token);
5358                 } else if (tb->module->dynamic_image == assembly) {
5359                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5360                 } else {
5361                         MonoType *type;
5362                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5363                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5364                 }
5365         } else if (strcmp (klass->name, "MonoType") == 0) {
5366                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5367                 MonoClass *mc = mono_class_from_mono_type (type);
5368                 token = mono_metadata_token_from_dor (
5369                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5370         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5371                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5372                 token = mono_metadata_token_from_dor (
5373                         mono_image_typedef_or_ref (assembly, type));
5374         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5375                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5376                 token = mono_metadata_token_from_dor (
5377                         mono_image_typedef_or_ref (assembly, type));
5378         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5379                    strcmp (klass->name, "MonoMethod") == 0 ||
5380                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5381                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5382                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5383                 if (m->method->is_inflated) {
5384                         if (create_open_instance)
5385                                 token = mono_image_get_methodspec_token (assembly, m->method);
5386                         else
5387                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5388                 } else if ((m->method->klass->image == &assembly->image) &&
5389                          !m->method->klass->generic_class) {
5390                         static guint32 method_table_idx = 0xffffff;
5391                         if (m->method->klass->wastypebuilder) {
5392                                 /* we use the same token as the one that was assigned
5393                                  * to the Methodbuilder.
5394                                  * FIXME: do the equivalent for Fields.
5395                                  */
5396                                 token = m->method->token;
5397                         } else {
5398                                 /*
5399                                  * Each token should have a unique index, but the indexes are
5400                                  * assigned by managed code, so we don't know about them. An
5401                                  * easy solution is to count backwards...
5402                                  */
5403                                 method_table_idx --;
5404                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5405                         }
5406                 } else {
5407                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5408                 }
5409                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5410         } else if (strcmp (klass->name, "MonoField") == 0) {
5411                 MonoReflectionField *f = (MonoReflectionField *)obj;
5412                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5413                         static guint32 field_table_idx = 0xffffff;
5414                         field_table_idx --;
5415                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5416                 } else {
5417                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5418                 }
5419                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5420         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5421                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5422                 token = mono_image_get_array_token (assembly, m);
5423         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5424                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5425                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5426         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5427                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5428                 token = mono_metadata_token_from_dor (
5429                         mono_image_typedef_or_ref (assembly, type));
5430         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5431                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5432                 token = mono_image_get_field_on_inst_token (assembly, f);
5433         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5434                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5435                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5436                 if (!mono_error_ok (error))
5437                         return 0;
5438         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5439                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5440                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5441                 if (!mono_error_ok (error))
5442                         return 0;
5443         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5444                 MonoReflectionType *type = (MonoReflectionType *)obj;
5445                 token = mono_metadata_token_from_dor (
5446                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5447         } else {
5448                 g_error ("requested token for %s\n", klass->name);
5449         }
5450
5451         if (register_token)
5452                 mono_image_register_token (assembly, token, obj);
5453
5454         return token;
5455 }
5456
5457 /*
5458  * mono_image_register_token:
5459  *
5460  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5461  * the Module.ResolveXXXToken () methods to work.
5462  */
5463 void
5464 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5465 {
5466         MonoObject *prev;
5467
5468         dynamic_image_lock (assembly);
5469         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5470         if (prev) {
5471                 /* There could be multiple MethodInfo objects with the same token */
5472                 //g_assert (prev == obj);
5473         } else {
5474                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5475         }
5476         dynamic_image_unlock (assembly);
5477 }
5478
5479 static MonoDynamicImage*
5480 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5481 {
5482         static const guchar entrycode [16] = {0xff, 0x25, 0};
5483         MonoDynamicImage *image;
5484         int i;
5485
5486         const char *version;
5487
5488         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5489                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5490         else
5491                 version = mono_get_runtime_info ()->runtime_version;
5492
5493 #if HAVE_BOEHM_GC
5494         /* The MonoGHashTable's need GC tracking */
5495         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5496 #else
5497         image = g_new0 (MonoDynamicImage, 1);
5498 #endif
5499
5500         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5501         
5502         /*g_print ("created image %p\n", image);*/
5503         /* keep in sync with image.c */
5504         image->image.name = assembly_name;
5505         image->image.assembly_name = image->image.name; /* they may be different */
5506         image->image.module_name = module_name;
5507         image->image.version = g_strdup (version);
5508         image->image.md_version_major = 1;
5509         image->image.md_version_minor = 1;
5510         image->image.dynamic = TRUE;
5511
5512         image->image.references = g_new0 (MonoAssembly*, 1);
5513         image->image.references [0] = NULL;
5514
5515         mono_image_init (&image->image);
5516
5517         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5518         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5519         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5520         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5521         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5522         image->handleref = g_hash_table_new (NULL, NULL);
5523         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5524         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5525         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5526         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5527         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5528         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5529         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5530         image->gen_params = g_ptr_array_new ();
5531         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5532
5533         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5534         string_heap_init (&image->sheap);
5535         mono_image_add_stream_data (&image->us, "", 1);
5536         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5537         /* import tables... */
5538         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5539         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5540         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5541         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5542         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5543         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5544         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5545         stream_data_align (&image->code);
5546
5547         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5548
5549         for (i=0; i < MONO_TABLE_NUM; ++i) {
5550                 image->tables [i].next_idx = 1;
5551                 image->tables [i].columns = table_sizes [i];
5552         }
5553
5554         image->image.assembly = (MonoAssembly*)assembly;
5555         image->run = assembly->run;
5556         image->save = assembly->save;
5557         image->pe_kind = 0x1; /* ILOnly */
5558         image->machine = 0x14c; /* I386 */
5559         
5560         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5561
5562         dynamic_images_lock ();
5563
5564         if (!dynamic_images)
5565                 dynamic_images = g_ptr_array_new ();
5566
5567         g_ptr_array_add (dynamic_images, image);
5568
5569         dynamic_images_unlock ();
5570
5571         return image;
5572 }
5573 #endif
5574
5575 static void
5576 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5577 {
5578         g_free (key);
5579 }
5580
5581 static void
5582 release_hashtable (MonoGHashTable **hash)
5583 {
5584         if (*hash) {
5585                 mono_g_hash_table_destroy (*hash);
5586                 *hash = NULL;
5587         }
5588 }
5589
5590 void
5591 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5592 {
5593         release_hashtable (&image->token_fixups);
5594         release_hashtable (&image->handleref_managed);
5595         release_hashtable (&image->tokens);
5596         release_hashtable (&image->remapped_tokens);
5597         release_hashtable (&image->generic_def_objects);
5598         release_hashtable (&image->methodspec);
5599 }
5600
5601 // Free dynamic image pass one: Free resources but not image itself
5602 void
5603 mono_dynamic_image_free (MonoDynamicImage *image)
5604 {
5605         MonoDynamicImage *di = image;
5606         GList *list;
5607         int i;
5608
5609         if (di->methodspec)
5610                 mono_g_hash_table_destroy (di->methodspec);
5611         if (di->typespec)
5612                 g_hash_table_destroy (di->typespec);
5613         if (di->typeref)
5614                 g_hash_table_destroy (di->typeref);
5615         if (di->handleref)
5616                 g_hash_table_destroy (di->handleref);
5617         if (di->handleref_managed)
5618                 mono_g_hash_table_destroy (di->handleref_managed);
5619         if (di->tokens)
5620                 mono_g_hash_table_destroy (di->tokens);
5621         if (di->remapped_tokens)
5622                 mono_g_hash_table_destroy (di->remapped_tokens);
5623         if (di->generic_def_objects)
5624                 mono_g_hash_table_destroy (di->generic_def_objects);
5625         if (di->blob_cache) {
5626                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5627                 g_hash_table_destroy (di->blob_cache);
5628         }
5629         if (di->standalonesig_cache)
5630                 g_hash_table_destroy (di->standalonesig_cache);
5631         for (list = di->array_methods; list; list = list->next) {
5632                 ArrayMethod *am = (ArrayMethod *)list->data;
5633                 g_free (am->sig);
5634                 g_free (am->name);
5635                 g_free (am);
5636         }
5637         g_list_free (di->array_methods);
5638         if (di->gen_params) {
5639                 for (i = 0; i < di->gen_params->len; i++) {
5640                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5641                         mono_gc_deregister_root ((char*) &entry->gparam);
5642                         g_free (entry);
5643                 }
5644                 g_ptr_array_free (di->gen_params, TRUE);
5645         }
5646         if (di->token_fixups)
5647                 mono_g_hash_table_destroy (di->token_fixups);
5648         if (di->method_to_table_idx)
5649                 g_hash_table_destroy (di->method_to_table_idx);
5650         if (di->field_to_table_idx)
5651                 g_hash_table_destroy (di->field_to_table_idx);
5652         if (di->method_aux_hash)
5653                 g_hash_table_destroy (di->method_aux_hash);
5654         if (di->vararg_aux_hash)
5655                 g_hash_table_destroy (di->vararg_aux_hash);
5656         g_free (di->strong_name);
5657         g_free (di->win32_res);
5658         if (di->public_key)
5659                 g_free (di->public_key);
5660
5661         /*g_print ("string heap destroy for image %p\n", di);*/
5662         mono_dynamic_stream_reset (&di->sheap);
5663         mono_dynamic_stream_reset (&di->code);
5664         mono_dynamic_stream_reset (&di->resources);
5665         mono_dynamic_stream_reset (&di->us);
5666         mono_dynamic_stream_reset (&di->blob);
5667         mono_dynamic_stream_reset (&di->tstream);
5668         mono_dynamic_stream_reset (&di->guid);
5669         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5670                 g_free (di->tables [i].values);
5671         }
5672
5673         dynamic_images_lock ();
5674
5675         if (dynamic_images)
5676                 g_ptr_array_remove (dynamic_images, di);
5677
5678         dynamic_images_unlock ();
5679 }
5680
5681 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5682 void
5683 mono_dynamic_image_free_image (MonoDynamicImage *image)
5684 {
5685         /* See create_dynamic_mono_image () */
5686 #if HAVE_BOEHM_GC
5687         /* Allocated using GC_MALLOC */
5688 #else
5689         g_free (image);
5690 #endif
5691 }
5692
5693 #ifndef DISABLE_REFLECTION_EMIT
5694
5695 /*
5696  * mono_image_basic_init:
5697  * @assembly: an assembly builder object
5698  *
5699  * Create the MonoImage that represents the assembly builder and setup some
5700  * of the helper hash table and the basic metadata streams.
5701  */
5702 void
5703 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5704 {
5705         MonoDynamicAssembly *assembly;
5706         MonoDynamicImage *image;
5707         MonoDomain *domain = mono_object_domain (assemblyb);
5708         
5709         if (assemblyb->dynamic_assembly)
5710                 return;
5711
5712 #if HAVE_BOEHM_GC
5713         /* assembly->assembly.image might be GC allocated */
5714         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5715 #else
5716         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5717 #endif
5718
5719         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5720         
5721         assembly->assembly.ref_count = 1;
5722         assembly->assembly.dynamic = TRUE;
5723         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5724         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5725         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5726         if (assemblyb->culture)
5727                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5728         else
5729                 assembly->assembly.aname.culture = g_strdup ("");
5730
5731         if (assemblyb->version) {
5732                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5733                         char **version = g_strsplit (vstr, ".", 4);
5734                         char **parts = version;
5735                         assembly->assembly.aname.major = atoi (*parts++);
5736                         assembly->assembly.aname.minor = atoi (*parts++);
5737                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5738                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5739
5740                         g_strfreev (version);
5741                         g_free (vstr);
5742         } else {
5743                         assembly->assembly.aname.major = 0;
5744                         assembly->assembly.aname.minor = 0;
5745                         assembly->assembly.aname.build = 0;
5746                         assembly->assembly.aname.revision = 0;
5747         }
5748
5749         assembly->run = assemblyb->access != 2;
5750         assembly->save = assemblyb->access != 1;
5751         assembly->domain = domain;
5752
5753         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5754         image->initial_image = TRUE;
5755         assembly->assembly.aname.name = image->image.name;
5756         assembly->assembly.image = &image->image;
5757         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5758                 /* -1 to correct for the trailing NULL byte */
5759                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5760                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5761                 }
5762                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5763         }
5764
5765         mono_domain_assemblies_lock (domain);
5766         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5767         mono_domain_assemblies_unlock (domain);
5768
5769         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5770         
5771         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5772         
5773         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5774 }
5775
5776 #endif /* !DISABLE_REFLECTION_EMIT */
5777
5778 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5779
5780 static int
5781 calc_section_size (MonoDynamicImage *assembly)
5782 {
5783         int nsections = 0;
5784
5785         /* alignment constraints */
5786         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5787         g_assert ((assembly->code.index % 4) == 0);
5788         assembly->meta_size += 3;
5789         assembly->meta_size &= ~3;
5790         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5791         g_assert ((assembly->resources.index % 4) == 0);
5792
5793         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5794         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5795         nsections++;
5796
5797         if (assembly->win32_res) {
5798                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5799
5800                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5801                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5802                 nsections++;
5803         }
5804
5805         assembly->sections [MONO_SECTION_RELOC].size = 12;
5806         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5807         nsections++;
5808
5809         return nsections;
5810 }
5811
5812 typedef struct {
5813         guint32 id;
5814         guint32 offset;
5815         GSList *children;
5816         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5817 } ResTreeNode;
5818
5819 static int
5820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5821 {
5822         ResTreeNode *t1 = (ResTreeNode*)a;
5823         ResTreeNode *t2 = (ResTreeNode*)b;
5824
5825         return t1->id - t2->id;
5826 }
5827
5828 /*
5829  * resource_tree_create:
5830  *
5831  *  Organize the resources into a resource tree.
5832  */
5833 static ResTreeNode *
5834 resource_tree_create (MonoArray *win32_resources)
5835 {
5836         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5837         GSList *l;
5838         int i;
5839
5840         tree = g_new0 (ResTreeNode, 1);
5841         
5842         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5843                 MonoReflectionWin32Resource *win32_res =
5844                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5845
5846                 /* Create node */
5847
5848                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5849                 lang_node = g_new0 (ResTreeNode, 1);
5850                 lang_node->id = win32_res->lang_id;
5851                 lang_node->win32_res = win32_res;
5852
5853                 /* Create type node if neccesary */
5854                 type_node = NULL;
5855                 for (l = tree->children; l; l = l->next)
5856                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5857                                 type_node = (ResTreeNode*)l->data;
5858                                 break;
5859                         }
5860
5861                 if (!type_node) {
5862                         type_node = g_new0 (ResTreeNode, 1);
5863                         type_node->id = win32_res->res_type;
5864
5865                         /* 
5866                          * The resource types have to be sorted otherwise
5867                          * Windows Explorer can't display the version information.
5868                          */
5869                         tree->children = g_slist_insert_sorted (tree->children, 
5870                                 type_node, resource_tree_compare_by_id);
5871                 }
5872
5873                 /* Create res node if neccesary */
5874                 res_node = NULL;
5875                 for (l = type_node->children; l; l = l->next)
5876                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5877                                 res_node = (ResTreeNode*)l->data;
5878                                 break;
5879                         }
5880
5881                 if (!res_node) {
5882                         res_node = g_new0 (ResTreeNode, 1);
5883                         res_node->id = win32_res->res_id;
5884                         type_node->children = g_slist_append (type_node->children, res_node);
5885                 }
5886
5887                 res_node->children = g_slist_append (res_node->children, lang_node);
5888         }
5889
5890         return tree;
5891 }
5892
5893 /*
5894  * resource_tree_encode:
5895  * 
5896  *   Encode the resource tree into the format used in the PE file.
5897  */
5898 static void
5899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5900 {
5901         char *entries;
5902         MonoPEResourceDir dir;
5903         MonoPEResourceDirEntry dir_entry;
5904         MonoPEResourceDataEntry data_entry;
5905         GSList *l;
5906         guint32 res_id_entries;
5907
5908         /*
5909          * For the format of the resource directory, see the article
5910          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5911          * Matt Pietrek
5912          */
5913
5914         memset (&dir, 0, sizeof (dir));
5915         memset (&dir_entry, 0, sizeof (dir_entry));
5916         memset (&data_entry, 0, sizeof (data_entry));
5917
5918         g_assert (sizeof (dir) == 16);
5919         g_assert (sizeof (dir_entry) == 8);
5920         g_assert (sizeof (data_entry) == 16);
5921
5922         node->offset = p - begin;
5923
5924         /* IMAGE_RESOURCE_DIRECTORY */
5925         res_id_entries = g_slist_length (node->children);
5926         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5927
5928         memcpy (p, &dir, sizeof (dir));
5929         p += sizeof (dir);
5930
5931         /* Reserve space for entries */
5932         entries = p;
5933         p += sizeof (dir_entry) * res_id_entries;
5934
5935         /* Write children */
5936         for (l = node->children; l; l = l->next) {
5937                 ResTreeNode *child = (ResTreeNode*)l->data;
5938
5939                 if (child->win32_res) {
5940                         guint32 size;
5941
5942                         child->offset = p - begin;
5943
5944                         /* IMAGE_RESOURCE_DATA_ENTRY */
5945                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5946                         size = mono_array_length (child->win32_res->res_data);
5947                         data_entry.rde_size = GUINT32_TO_LE (size);
5948
5949                         memcpy (p, &data_entry, sizeof (data_entry));
5950                         p += sizeof (data_entry);
5951
5952                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5953                         p += size;
5954                 } else {
5955                         resource_tree_encode (child, begin, p, &p);
5956                 }
5957         }
5958
5959         /* IMAGE_RESOURCE_ENTRY */
5960         for (l = node->children; l; l = l->next) {
5961                 ResTreeNode *child = (ResTreeNode*)l->data;
5962
5963                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5964                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5965
5966                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5967                 entries += sizeof (dir_entry);
5968         }
5969
5970         *endbuf = p;
5971 }
5972
5973 static void
5974 resource_tree_free (ResTreeNode * node)
5975 {
5976         GSList * list;
5977         for (list = node->children; list; list = list->next)
5978                 resource_tree_free ((ResTreeNode*)list->data);
5979         g_slist_free(node->children);
5980         g_free (node);
5981 }
5982
5983 static void
5984 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5985 {
5986         char *buf;
5987         char *p;
5988         guint32 size, i;
5989         MonoReflectionWin32Resource *win32_res;
5990         ResTreeNode *tree;
5991
5992         if (!assemblyb->win32_resources)
5993                 return;
5994
5995         /*
5996          * Resources are stored in a three level tree inside the PE file.
5997          * - level one contains a node for each type of resource
5998          * - level two contains a node for each resource
5999          * - level three contains a node for each instance of a resource for a
6000          *   specific language.
6001          */
6002
6003         tree = resource_tree_create (assemblyb->win32_resources);
6004
6005         /* Estimate the size of the encoded tree */
6006         size = 0;
6007         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6008                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6009                 size += mono_array_length (win32_res->res_data);
6010         }
6011         /* Directory structure */
6012         size += mono_array_length (assemblyb->win32_resources) * 256;
6013         p = buf = (char *)g_malloc (size);
6014
6015         resource_tree_encode (tree, p, p, &p);
6016
6017         g_assert (p - buf <= size);
6018
6019         assembly->win32_res = (char *)g_malloc (p - buf);
6020         assembly->win32_res_size = p - buf;
6021         memcpy (assembly->win32_res, buf, p - buf);
6022
6023         g_free (buf);
6024         resource_tree_free (tree);
6025 }
6026
6027 static void
6028 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6029 {
6030         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6031         int i;
6032
6033         p += sizeof (MonoPEResourceDir);
6034         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6035                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6036                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6037                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6038                         fixup_resource_directory (res_section, child, rva);
6039                 } else {
6040                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6041                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6042                 }
6043
6044                 p += sizeof (MonoPEResourceDirEntry);
6045         }
6046 }
6047
6048 static void
6049 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6050 {
6051         guint32 dummy;
6052         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6053                 g_error ("WriteFile returned %d\n", GetLastError ());
6054 }
6055
6056 /*
6057  * mono_image_create_pefile:
6058  * @mb: a module builder object
6059  * 
6060  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6061  * assembly->pefile where it can be easily retrieved later in chunks.
6062  */
6063 gboolean
6064 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6065 {
6066         MonoMSDOSHeader *msdos;
6067         MonoDotNetHeader *header;
6068         MonoSectionTable *section;
6069         MonoCLIHeader *cli_header;
6070         guint32 size, image_size, virtual_base, text_offset;
6071         guint32 header_start, section_start, file_offset, virtual_offset;
6072         MonoDynamicImage *assembly;
6073         MonoReflectionAssemblyBuilder *assemblyb;
6074         MonoDynamicStream pefile_stream = {0};
6075         MonoDynamicStream *pefile = &pefile_stream;
6076         int i, nsections;
6077         guint32 *rva, value;
6078         guchar *p;
6079         static const unsigned char msheader[] = {
6080                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6081                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6082                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6083                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6084                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6085                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6086                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6087                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6088         };
6089
6090         mono_error_init (error);
6091
6092         assemblyb = mb->assemblyb;
6093
6094         mono_image_basic_init (assemblyb);
6095         assembly = mb->dynamic_image;
6096
6097         assembly->pe_kind = assemblyb->pe_kind;
6098         assembly->machine = assemblyb->machine;
6099         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6100         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6101         
6102         if (!mono_image_build_metadata (mb, error))
6103                 return FALSE;
6104         
6105
6106         if (mb->is_main && assemblyb->resources) {
6107                 int len = mono_array_length (assemblyb->resources);
6108                 for (i = 0; i < len; ++i)
6109                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6110         }
6111
6112         if (mb->resources) {
6113                 int len = mono_array_length (mb->resources);
6114                 for (i = 0; i < len; ++i)
6115                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6116         }
6117
6118         if (!build_compressed_metadata (assembly, error))
6119                 return FALSE;
6120
6121         if (mb->is_main)
6122                 assembly_add_win32_resources (assembly, assemblyb);
6123
6124         nsections = calc_section_size (assembly);
6125         
6126         /* The DOS header and stub */
6127         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6128         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6129
6130         /* the dotnet header */
6131         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6132
6133         /* the section tables */
6134         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6135
6136         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6137         virtual_offset = VIRT_ALIGN;
6138         image_size = 0;
6139
6140         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6141                 if (!assembly->sections [i].size)
6142                         continue;
6143                 /* align offsets */
6144                 file_offset += FILE_ALIGN - 1;
6145                 file_offset &= ~(FILE_ALIGN - 1);
6146                 virtual_offset += VIRT_ALIGN - 1;
6147                 virtual_offset &= ~(VIRT_ALIGN - 1);
6148
6149                 assembly->sections [i].offset = file_offset;
6150                 assembly->sections [i].rva = virtual_offset;
6151
6152                 file_offset += assembly->sections [i].size;
6153                 virtual_offset += assembly->sections [i].size;
6154                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6155         }
6156
6157         file_offset += FILE_ALIGN - 1;
6158         file_offset &= ~(FILE_ALIGN - 1);
6159
6160         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6161
6162         /* back-patch info */
6163         msdos = (MonoMSDOSHeader*)pefile->data;
6164         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6165
6166         header = (MonoDotNetHeader*)(pefile->data + header_start);
6167         header->pesig [0] = 'P';
6168         header->pesig [1] = 'E';
6169         
6170         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6171         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6172         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6173         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6174         if (assemblyb->pekind == 1) {
6175                 /* it's a dll */
6176                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6177         } else {
6178                 /* it's an exe */
6179                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6180         }
6181
6182         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6183
6184         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6185         header->pe.pe_major = 6;
6186         header->pe.pe_minor = 0;
6187         size = assembly->sections [MONO_SECTION_TEXT].size;
6188         size += FILE_ALIGN - 1;
6189         size &= ~(FILE_ALIGN - 1);
6190         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6191         size = assembly->sections [MONO_SECTION_RSRC].size;
6192         size += FILE_ALIGN - 1;
6193         size &= ~(FILE_ALIGN - 1);
6194         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6195         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6196         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6197         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6198         /* pe_rva_entry_point always at the beginning of the text section */
6199         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6200
6201         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6202         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6203         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6204         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6205         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6206         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6207         size = section_start;
6208         size += FILE_ALIGN - 1;
6209         size &= ~(FILE_ALIGN - 1);
6210         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6211         size = image_size;
6212         size += VIRT_ALIGN - 1;
6213         size &= ~(VIRT_ALIGN - 1);
6214         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6215
6216         /*
6217         // Translate the PEFileKind value to the value expected by the Windows loader
6218         */
6219         {
6220                 short kind;
6221
6222                 /*
6223                 // PEFileKinds.Dll == 1
6224                 // PEFileKinds.ConsoleApplication == 2
6225                 // PEFileKinds.WindowApplication == 3
6226                 //
6227                 // need to get:
6228                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6229                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6230                 */
6231                 if (assemblyb->pekind == 3)
6232                         kind = 2;
6233                 else
6234                         kind = 3;
6235                 
6236                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6237         }    
6238         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6239         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6240         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6241         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6242         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6243         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6244
6245         /* fill data directory entries */
6246
6247         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6248         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6249
6250         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6251         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6252
6253         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6254         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6255         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6256         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6257         /* patch entrypoint name */
6258         if (assemblyb->pekind == 1)
6259                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6260         else
6261                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6262         /* patch imported function RVA name */
6263         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6264         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6265
6266         /* the import table */
6267         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6268         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6269         /* patch imported dll RVA name and other entries in the dir */
6270         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6271         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6272         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6273         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6274         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6275         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6276
6277         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6278         value = (assembly->text_rva + assembly->imp_names_offset);
6279         *p++ = (value) & 0xff;
6280         *p++ = (value >> 8) & (0xff);
6281         *p++ = (value >> 16) & (0xff);
6282         *p++ = (value >> 24) & (0xff);
6283
6284         /* the CLI header info */
6285         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6286         cli_header->ch_size = GUINT32_FROM_LE (72);
6287         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6288         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6289         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6290         if (assemblyb->entry_point) {
6291                 guint32 table_idx = 0;
6292                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6293                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6294                         table_idx = methodb->table_idx;
6295                 } else {
6296                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6297                 }
6298                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6299         } else {
6300                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6301         }
6302         /* The embedded managed resources */
6303         text_offset = assembly->text_rva + assembly->code.index;
6304         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6305         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6306         text_offset += assembly->resources.index;
6307         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6308         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6309         text_offset += assembly->meta_size;
6310         if (assembly->strong_name_size) {
6311                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6312                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6313                 text_offset += assembly->strong_name_size;
6314         }
6315
6316         /* write the section tables and section content */
6317         section = (MonoSectionTable*)(pefile->data + section_start);
6318         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6319                 static const char section_names [][7] = {
6320                         ".text", ".rsrc", ".reloc"
6321                 };
6322                 if (!assembly->sections [i].size)
6323                         continue;
6324                 strcpy (section->st_name, section_names [i]);
6325                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6326                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6327                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6328                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6329                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6330                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6331                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6332                 section ++;
6333         }
6334         
6335         checked_write_file (file, pefile->data, pefile->index);
6336         
6337         mono_dynamic_stream_reset (pefile);
6338         
6339         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6340                 if (!assembly->sections [i].size)
6341                         continue;
6342                 
6343                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6344                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6345                 
6346                 switch (i) {
6347                 case MONO_SECTION_TEXT:
6348                         /* patch entry point */
6349                         p = (guchar*)(assembly->code.data + 2);
6350                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6351                         *p++ = (value) & 0xff;
6352                         *p++ = (value >> 8) & 0xff;
6353                         *p++ = (value >> 16) & 0xff;
6354                         *p++ = (value >> 24) & 0xff;
6355                 
6356                         checked_write_file (file, assembly->code.data, assembly->code.index);
6357                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6358                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6359                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6360                                 
6361
6362                         g_free (assembly->image.raw_metadata);
6363                         break;
6364                 case MONO_SECTION_RELOC: {
6365                         struct {
6366                                 guint32 page_rva;
6367                                 guint32 block_size;
6368                                 guint16 type_and_offset;
6369                                 guint16 term;
6370                         } reloc;
6371                         
6372                         g_assert (sizeof (reloc) == 12);
6373                         
6374                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6375                         reloc.block_size = GUINT32_FROM_LE (12);
6376                         
6377                         /* 
6378                          * the entrypoint is always at the start of the text section 
6379                          * 3 is IMAGE_REL_BASED_HIGHLOW
6380                          * 2 is patch_size_rva - text_rva
6381                          */
6382                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6383                         reloc.term = 0;
6384                         
6385                         checked_write_file (file, &reloc, sizeof (reloc));
6386                         
6387                         break;
6388                 }
6389                 case MONO_SECTION_RSRC:
6390                         if (assembly->win32_res) {
6391
6392                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6393                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6394                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6395                         }
6396                         break;
6397                 default:
6398                         g_assert_not_reached ();
6399                 }
6400         }
6401         
6402         /* check that the file is properly padded */
6403         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6404                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6405         if (! SetEndOfFile (file))
6406                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6407         
6408         mono_dynamic_stream_reset (&assembly->code);
6409         mono_dynamic_stream_reset (&assembly->us);
6410         mono_dynamic_stream_reset (&assembly->blob);
6411         mono_dynamic_stream_reset (&assembly->guid);
6412         mono_dynamic_stream_reset (&assembly->sheap);
6413
6414         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6415         g_hash_table_destroy (assembly->blob_cache);
6416         assembly->blob_cache = NULL;
6417
6418         return TRUE;
6419 }
6420
6421 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6422
6423 gboolean
6424 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6425 {
6426         g_assert_not_reached ();
6427 }
6428
6429 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6430
6431 #ifndef DISABLE_REFLECTION_EMIT
6432
6433 MonoReflectionModule *
6434 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6435 {
6436         MonoError error;
6437         MonoReflectionModule *result = NULL;
6438         char *name;
6439         MonoImage *image;
6440         MonoImageOpenStatus status;
6441         MonoDynamicAssembly *assembly;
6442         guint32 module_count;
6443         MonoImage **new_modules;
6444         gboolean *new_modules_loaded;
6445         
6446         name = mono_string_to_utf8 (fileName);
6447
6448         image = mono_image_open (name, &status);
6449         if (!image) {
6450                 MonoException *exc;
6451                 if (status == MONO_IMAGE_ERROR_ERRNO)
6452                         exc = mono_get_exception_file_not_found (fileName);
6453                 else
6454                         exc = mono_get_exception_bad_image_format (name);
6455                 g_free (name);
6456                 mono_raise_exception (exc);
6457         }
6458
6459         g_free (name);
6460
6461         assembly = ab->dynamic_assembly;
6462         image->assembly = (MonoAssembly*)assembly;
6463
6464         module_count = image->assembly->image->module_count;
6465         new_modules = g_new0 (MonoImage *, module_count + 1);
6466         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6467
6468         if (image->assembly->image->modules)
6469                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6470         if (image->assembly->image->modules_loaded)
6471                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6472         new_modules [module_count] = image;
6473         new_modules_loaded [module_count] = TRUE;
6474         mono_image_addref (image);
6475
6476         g_free (image->assembly->image->modules);
6477         image->assembly->image->modules = new_modules;
6478         image->assembly->image->modules_loaded = new_modules_loaded;
6479         image->assembly->image->module_count ++;
6480
6481         mono_assembly_load_references (image, &status);
6482         if (status) {
6483                 mono_image_close (image);
6484                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6485         }
6486
6487         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6488         mono_error_raise_exception (&error); /* FIXME don't raise here */
6489         return result;
6490 }
6491
6492 #endif /* DISABLE_REFLECTION_EMIT */
6493
6494 /*
6495  * We need to return always the same object for MethodInfo, FieldInfo etc..
6496  * but we need to consider the reflected type.
6497  * type uses a different hash, since it uses custom hash/equal functions.
6498  */
6499
6500 typedef struct {
6501         gpointer item;
6502         MonoClass *refclass;
6503 } ReflectedEntry;
6504
6505 static gboolean
6506 reflected_equal (gconstpointer a, gconstpointer b) {
6507         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6508         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6509
6510         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6511 }
6512
6513 static guint
6514 reflected_hash (gconstpointer a) {
6515         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6516         return mono_aligned_addr_hash (ea->item);
6517 }
6518
6519 #define CHECK_OBJECT(t,p,k)     \
6520         do {    \
6521                 t _obj; \
6522                 ReflectedEntry e;       \
6523                 e.item = (p);   \
6524                 e.refclass = (k);       \
6525                 mono_domain_lock (domain);      \
6526                 if (!domain->refobject_hash)    \
6527                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6528                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6529                         mono_domain_unlock (domain);    \
6530                         return _obj;    \
6531                 }       \
6532         mono_domain_unlock (domain); \
6533         } while (0)
6534
6535 #ifdef HAVE_BOEHM_GC
6536 /* ReflectedEntry doesn't need to be GC tracked */
6537 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6538 #define FREE_REFENTRY(entry) g_free ((entry))
6539 #define REFENTRY_REQUIRES_CLEANUP
6540 #else
6541 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6542 /* FIXME: */
6543 #define FREE_REFENTRY(entry)
6544 #endif
6545
6546 #define CACHE_OBJECT(t,p,o,k)   \
6547         do {    \
6548                 t _obj; \
6549         ReflectedEntry pe; \
6550         pe.item = (p); \
6551         pe.refclass = (k); \
6552         mono_domain_lock (domain); \
6553                 if (!domain->refobject_hash)    \
6554                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6555         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6556         if (!_obj) { \
6557                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6558                     e->item = (p);      \
6559                     e->refclass = (k);  \
6560                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6561             _obj = o; \
6562         } \
6563                 mono_domain_unlock (domain);    \
6564         return _obj; \
6565         } while (0)
6566
6567 static void
6568 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6569 {
6570         mono_domain_lock (domain);
6571         if (domain->refobject_hash) {
6572         ReflectedEntry pe;
6573                 gpointer orig_pe, orig_value;
6574
6575                 pe.item = o;
6576                 pe.refclass = klass;
6577                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6578                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6579                         FREE_REFENTRY (orig_pe);
6580                 }
6581         }
6582         mono_domain_unlock (domain);
6583 }
6584
6585 #ifdef REFENTRY_REQUIRES_CLEANUP
6586 static void
6587 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6588 {
6589         FREE_REFENTRY (key);
6590 }
6591 #endif
6592
6593 void
6594 mono_reflection_cleanup_domain (MonoDomain *domain)
6595 {
6596         if (domain->refobject_hash) {
6597 /*let's avoid scanning the whole hashtable if not needed*/
6598 #ifdef REFENTRY_REQUIRES_CLEANUP
6599                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6600 #endif
6601                 mono_g_hash_table_destroy (domain->refobject_hash);
6602                 domain->refobject_hash = NULL;
6603         }
6604 }
6605
6606 #ifndef DISABLE_REFLECTION_EMIT
6607 static gpointer
6608 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6609 {
6610         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6611 }
6612
6613 static gpointer
6614 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6615 {
6616         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6617 }
6618
6619 void
6620 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6621 {
6622         MonoDynamicImage *image = moduleb->dynamic_image;
6623         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6624         if (!image) {
6625                 MonoError error;
6626                 int module_count;
6627                 MonoImage **new_modules;
6628                 MonoImage *ass;
6629                 char *name, *fqname;
6630                 /*
6631                  * FIXME: we already created an image in mono_image_basic_init (), but
6632                  * we don't know which module it belongs to, since that is only 
6633                  * determined at assembly save time.
6634                  */
6635                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6636                 name = mono_string_to_utf8 (ab->name);
6637                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6638                 if (!mono_error_ok (&error)) {
6639                         g_free (name);
6640                         mono_error_raise_exception (&error);
6641                 }
6642                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6643
6644                 moduleb->module.image = &image->image;
6645                 moduleb->dynamic_image = image;
6646                 register_module (mono_object_domain (moduleb), moduleb, image);
6647
6648                 /* register the module with the assembly */
6649                 ass = ab->dynamic_assembly->assembly.image;
6650                 module_count = ass->module_count;
6651                 new_modules = g_new0 (MonoImage *, module_count + 1);
6652
6653                 if (ass->modules)
6654                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6655                 new_modules [module_count] = &image->image;
6656                 mono_image_addref (&image->image);
6657
6658                 g_free (ass->modules);
6659                 ass->modules = new_modules;
6660                 ass->module_count ++;
6661         }
6662 }
6663
6664 void
6665 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6666 {
6667         MonoDynamicImage *image = moduleb->dynamic_image;
6668
6669         g_assert (type->type);
6670         image->wrappers_type = mono_class_from_mono_type (type->type);
6671 }
6672
6673 #endif
6674
6675 /*
6676  * mono_assembly_get_object:
6677  * @domain: an app domain
6678  * @assembly: an assembly
6679  *
6680  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6681  */
6682 MonoReflectionAssembly*
6683 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6684 {
6685         MonoError error;
6686         MonoReflectionAssembly *result;
6687         result = mono_assembly_get_object_checked (domain, assembly, &error);
6688         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6689         return result;
6690 }
6691 /*
6692  * mono_assembly_get_object_checked:
6693  * @domain: an app domain
6694  * @assembly: an assembly
6695  *
6696  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6697  */
6698 MonoReflectionAssembly*
6699 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6700 {
6701         MonoReflectionAssembly *res;
6702         
6703         mono_error_init (error);
6704
6705         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6706         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6707         if (!res)
6708                 return NULL;
6709         res->assembly = assembly;
6710
6711         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6712 }
6713
6714
6715
6716 MonoReflectionModule*   
6717 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6718 {
6719         MonoError error;
6720         MonoReflectionModule *result;
6721         result = mono_module_get_object_checked (domain, image, &error);
6722         mono_error_raise_exception (&error);
6723         return result;
6724 }
6725
6726 MonoReflectionModule*
6727 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6728 {
6729         MonoReflectionModule *res;
6730         char* basename;
6731         
6732         mono_error_init (error);
6733         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6734         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6735         if (!res)
6736                 return NULL;
6737
6738         res->image = image;
6739         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6740         if (!assm_obj)
6741                 return NULL;
6742         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6743
6744         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6745         basename = g_path_get_basename (image->name);
6746         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6747         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6748         
6749         g_free (basename);
6750
6751         if (image->assembly->image == image) {
6752                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6753         } else {
6754                 int i;
6755                 res->token = 0;
6756                 if (image->assembly->image->modules) {
6757                         for (i = 0; i < image->assembly->image->module_count; i++) {
6758                                 if (image->assembly->image->modules [i] == image)
6759                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6760                         }
6761                         g_assert (res->token);
6762                 }
6763         }
6764
6765         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6766 }
6767
6768 MonoReflectionModule*
6769 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6770 {
6771         MonoError error;
6772         MonoReflectionModule *result;
6773         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6774         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6775         return result;
6776 }
6777
6778 MonoReflectionModule*
6779 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6780 {
6781         MonoReflectionModule *res;
6782         MonoTableInfo *table;
6783         guint32 cols [MONO_FILE_SIZE];
6784         const char *name;
6785         guint32 i, name_idx;
6786         const char *val;
6787         
6788         mono_error_init (error);
6789
6790         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6791         if (!res)
6792                 return NULL;
6793
6794         table = &image->tables [MONO_TABLE_FILE];
6795         g_assert (table_index < table->rows);
6796         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6797
6798         res->image = NULL;
6799         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6800         if (!assm_obj)
6801                 return NULL;
6802         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6804
6805         /* Check whenever the row has a corresponding row in the moduleref table */
6806         table = &image->tables [MONO_TABLE_MODULEREF];
6807         for (i = 0; i < table->rows; ++i) {
6808                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809                 val = mono_metadata_string_heap (image, name_idx);
6810                 if (strcmp (val, name) == 0)
6811                         res->image = image->modules [i];
6812         }
6813
6814         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6819
6820         return res;
6821 }
6822
6823 static gboolean
6824 verify_safe_for_managed_space (MonoType *type)
6825 {
6826         switch (type->type) {
6827 #ifdef DEBUG_HARDER
6828         case MONO_TYPE_ARRAY:
6829                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6830         case MONO_TYPE_PTR:
6831                 return verify_safe_for_managed_space (type->data.type);
6832         case MONO_TYPE_SZARRAY:
6833                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834         case MONO_TYPE_GENERICINST: {
6835                 MonoGenericInst *inst = type->data.generic_class->inst;
6836                 int i;
6837                 if (!inst->is_open)
6838                         break;
6839                 for (i = 0; i < inst->type_argc; ++i)
6840                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6841                                 return FALSE;
6842                 return TRUE;
6843         }
6844 #endif
6845         case MONO_TYPE_VAR:
6846         case MONO_TYPE_MVAR:
6847                 return TRUE;
6848         default:
6849                 return TRUE;
6850         }
6851 }
6852
6853 static MonoType*
6854 mono_type_normalize (MonoType *type)
6855 {
6856         int i;
6857         MonoGenericClass *gclass;
6858         MonoGenericInst *ginst;
6859         MonoClass *gtd;
6860         MonoGenericContainer *gcontainer;
6861         MonoType **argv = NULL;
6862         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6863
6864         if (type->type != MONO_TYPE_GENERICINST)
6865                 return type;
6866
6867         gclass = type->data.generic_class;
6868         ginst = gclass->context.class_inst;
6869         if (!ginst->is_open)
6870                 return type;
6871
6872         gtd = gclass->container_class;
6873         gcontainer = gtd->generic_container;
6874         argv = g_newa (MonoType*, ginst->type_argc);
6875
6876         for (i = 0; i < ginst->type_argc; ++i) {
6877                 MonoType *t = ginst->type_argv [i], *norm;
6878                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879                         is_denorm_gtd = FALSE;
6880                 norm = mono_type_normalize (t);
6881                 argv [i] = norm;
6882                 if (norm != t)
6883                         requires_rebind = TRUE;
6884         }
6885
6886         if (is_denorm_gtd)
6887                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6888
6889         if (requires_rebind) {
6890                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6892         }
6893
6894         return type;
6895 }
6896 /*
6897  * mono_type_get_object:
6898  * @domain: an app domain
6899  * @type: a type
6900  *
6901  * Return an System.MonoType object representing the type @type.
6902  */
6903 MonoReflectionType*
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6905 {
6906         MonoError error;
6907         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908         mono_error_raise_exception (&error);
6909
6910         return ret;
6911 }
6912
6913 MonoReflectionType*
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6915 {
6916         MonoType *norm_type;
6917         MonoReflectionType *res;
6918         MonoClass *klass;
6919
6920         mono_error_init (error);
6921
6922         klass = mono_class_from_mono_type (type);
6923
6924         /*we must avoid using @type as it might have come
6925          * from a mono_metadata_type_dup and the caller
6926          * expects that is can be freed.
6927          * Using the right type from 
6928          */
6929         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6930
6931         /* void is very common */
6932         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933                 return (MonoReflectionType*)domain->typeof_void;
6934
6935         /*
6936          * If the vtable of the given class was already created, we can use
6937          * the MonoType from there and avoid all locking and hash table lookups.
6938          * 
6939          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940          * that the resulting object is different.   
6941          */
6942         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944                 if (vtable && vtable->type)
6945                         return (MonoReflectionType *)vtable->type;
6946         }
6947
6948         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949         mono_domain_lock (domain);
6950         if (!domain->type_hash)
6951                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6952                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954                 mono_domain_unlock (domain);
6955                 mono_loader_unlock ();
6956                 return res;
6957         }
6958
6959         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963          * artifact of how generics are encoded and should be transparent to managed code so we
6964          * need to weed out this diference when retrieving managed System.Type objects.
6965          */
6966         norm_type = mono_type_normalize (type);
6967         if (norm_type != type) {
6968                 res = mono_type_get_object_checked (domain, norm_type, error);
6969                 if (!mono_error_ok (error))
6970                         return NULL;
6971                 mono_g_hash_table_insert (domain->type_hash, type, res);
6972                 mono_domain_unlock (domain);
6973                 mono_loader_unlock ();
6974                 return res;
6975         }
6976
6977         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6979                 g_assert (0);
6980
6981         if (!verify_safe_for_managed_space (type)) {
6982                 mono_domain_unlock (domain);
6983                 mono_loader_unlock ();
6984                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6985                 return NULL;
6986         }
6987
6988         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989                 gboolean is_type_done = TRUE;
6990                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6993                 */
6994                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6996
6997                         if (gparam->owner && gparam->owner->is_method) {
6998                                 MonoMethod *method = gparam->owner->owner.method;
6999                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000                                         is_type_done = FALSE;
7001                         } else if (gparam->owner && !gparam->owner->is_method) {
7002                                 MonoClass *klass = gparam->owner->owner.klass;
7003                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004                                         is_type_done = FALSE;
7005                         }
7006                 } 
7007
7008                 /* g_assert_not_reached (); */
7009                 /* should this be considered an error condition? */
7010                 if (is_type_done && !type->byref) {
7011                         mono_domain_unlock (domain);
7012                         mono_loader_unlock ();
7013                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7014                 }
7015         }
7016         /* This is stored in vtables/JITted code so it has to be pinned */
7017         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018         if (!mono_error_ok (error))
7019                 return NULL;
7020
7021         res->type = type;
7022         mono_g_hash_table_insert (domain->type_hash, type, res);
7023
7024         if (type->type == MONO_TYPE_VOID)
7025                 domain->typeof_void = (MonoObject*)res;
7026
7027         mono_domain_unlock (domain);
7028         mono_loader_unlock ();
7029         return res;
7030 }
7031
7032 /*
7033  * mono_method_get_object:
7034  * @domain: an app domain
7035  * @method: a method
7036  * @refclass: the reflected type (can be NULL)
7037  *
7038  * Return an System.Reflection.MonoMethod object representing the method @method.
7039  */
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7042 {
7043         MonoError error;
7044         MonoReflectionMethod *ret = NULL;
7045         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046         mono_error_raise_exception (&error);
7047         return ret;
7048 }
7049
7050 /*
7051  * mono_method_get_object_checked:
7052  * @domain: an app domain
7053  * @method: a method
7054  * @refclass: the reflected type (can be NULL)
7055  * @error: set on error.
7056  *
7057  * Return an System.Reflection.MonoMethod object representing the method @method.
7058  * Returns NULL and sets @error on error.
7059  */
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7062 {
7063         /*
7064          * We use the same C representation for methods and constructors, but the type 
7065          * name in C# is different.
7066          */
7067         MonoReflectionType *rt;
7068         MonoClass *klass;
7069         MonoReflectionMethod *ret;
7070
7071         mono_error_init (error);
7072
7073         if (method->is_inflated) {
7074                 MonoReflectionGenericMethod *gret;
7075
7076                 if (!refclass)
7077                         refclass = method->klass;
7078                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7079                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7080                         klass = mono_class_get_mono_generic_cmethod_class ();
7081                 } else {
7082                         klass = mono_class_get_mono_generic_method_class ();
7083                 }
7084                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7085                 if (!mono_error_ok (error))
7086                         goto leave;
7087                 gret->method.method = method;
7088
7089                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7090
7091                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7092                 if (!mono_error_ok (error))
7093                     goto leave;
7094
7095                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7096
7097                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7098         }
7099
7100         if (!refclass)
7101                 refclass = method->klass;
7102
7103         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7104         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7105                 klass = mono_class_get_mono_cmethod_class ();
7106         }
7107         else {
7108                 klass = mono_class_get_mono_method_class ();
7109         }
7110         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7111         if (!mono_error_ok (error))
7112                 goto leave;
7113         ret->method = method;
7114
7115         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7116         if (!mono_error_ok (error))
7117                 goto leave;
7118
7119         MONO_OBJECT_SETREF (ret, reftype, rt);
7120
7121         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7122
7123 leave:
7124         g_assert (!mono_error_ok (error));
7125         return NULL;
7126 }
7127
7128 /*
7129  * mono_method_clear_object:
7130  *
7131  *   Clear the cached reflection objects for the dynamic method METHOD.
7132  */
7133 void
7134 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7135 {
7136         MonoClass *klass;
7137         g_assert (method_is_dynamic (method));
7138
7139         klass = method->klass;
7140         while (klass) {
7141                 clear_cached_object (domain, method, klass);
7142                 klass = klass->parent;
7143         }
7144         /* Added by mono_param_get_objects () */
7145         clear_cached_object (domain, &(method->signature), NULL);
7146         klass = method->klass;
7147         while (klass) {
7148                 clear_cached_object (domain, &(method->signature), klass);
7149                 klass = klass->parent;
7150         }
7151 }
7152
7153 /*
7154  * mono_field_get_object:
7155  * @domain: an app domain
7156  * @klass: a type
7157  * @field: a field
7158  *
7159  * Return an System.Reflection.MonoField object representing the field @field
7160  * in class @klass.
7161  */
7162 MonoReflectionField*
7163 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7164 {
7165         MonoError error;
7166         MonoReflectionField *result;
7167         result = mono_field_get_object_checked (domain, klass, field, &error);
7168         mono_error_raise_exception (&error);
7169         return result;
7170 }
7171
7172 /*
7173  * mono_field_get_object_checked:
7174  * @domain: an app domain
7175  * @klass: a type
7176  * @field: a field
7177  * @error: set on error
7178  *
7179  * Return an System.Reflection.MonoField object representing the field @field
7180  * in class @klass. On error, returns NULL and sets @error.
7181  */
7182 MonoReflectionField*
7183 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7184 {
7185         MonoReflectionType *rt;
7186         MonoReflectionField *res;
7187
7188         mono_error_init (error);
7189
7190         CHECK_OBJECT (MonoReflectionField *, field, klass);
7191         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7192         if (!res)
7193                 return NULL;
7194         res->klass = klass;
7195         res->field = field;
7196         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7197
7198         if (is_field_on_inst (field)) {
7199                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7200
7201                 rt = mono_type_get_object_checked (domain, field->type, error);
7202                 if (!mono_error_ok (error))
7203                         return NULL;
7204
7205                 MONO_OBJECT_SETREF (res, type, rt);
7206         } else {
7207                 if (field->type) {
7208                         rt = mono_type_get_object_checked (domain, field->type, error);
7209                         if (!mono_error_ok (error))
7210                                 return NULL;
7211
7212                         MONO_OBJECT_SETREF (res, type, rt);
7213                 }
7214                 res->attrs = mono_field_get_flags (field);
7215         }
7216         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7217 }
7218
7219 /*
7220  * mono_property_get_object:
7221  * @domain: an app domain
7222  * @klass: a type
7223  * @property: a property
7224  *
7225  * Return an System.Reflection.MonoProperty object representing the property @property
7226  * in class @klass.
7227  */
7228 MonoReflectionProperty*
7229 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7230 {
7231         MonoError error;
7232         MonoReflectionProperty *result;
7233         result = mono_property_get_object_checked (domain, klass, property, &error);
7234         mono_error_raise_exception (&error);
7235         return result;
7236 }
7237
7238 /**
7239  * mono_property_get_object:
7240  * @domain: an app domain
7241  * @klass: a type
7242  * @property: a property
7243  * @error: set on error
7244  *
7245  * Return an System.Reflection.MonoProperty object representing the property @property
7246  * in class @klass.  On error returns NULL and sets @error.
7247  */
7248 MonoReflectionProperty*
7249 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7250 {
7251         MonoReflectionProperty *res;
7252
7253         mono_error_init (error);
7254
7255         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7256         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7257         if (!res)
7258                 return NULL;
7259         res->klass = klass;
7260         res->property = property;
7261         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7262 }
7263
7264 /*
7265  * mono_event_get_object:
7266  * @domain: an app domain
7267  * @klass: a type
7268  * @event: a event
7269  *
7270  * Return an System.Reflection.MonoEvent object representing the event @event
7271  * in class @klass.
7272  */
7273 MonoReflectionEvent*
7274 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7275 {
7276         MonoError error;
7277         MonoReflectionEvent *result;
7278         result = mono_event_get_object_checked (domain, klass, event, &error);
7279         mono_error_raise_exception (&error);
7280         return result;
7281 }
7282
7283 /**
7284  * mono_event_get_object_checked:
7285  * @domain: an app domain
7286  * @klass: a type
7287  * @event: a event
7288  * @error: set on error
7289  *
7290  * Return an System.Reflection.MonoEvent object representing the event @event
7291  * in class @klass. On failure sets @error and returns NULL
7292  */
7293 MonoReflectionEvent*
7294 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7295 {
7296         MonoReflectionEvent *res;
7297         MonoReflectionMonoEvent *mono_event;
7298
7299         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7300         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7301         if (!mono_event)
7302                 return NULL;
7303         mono_event->klass = klass;
7304         mono_event->event = event;
7305         res = (MonoReflectionEvent*)mono_event;
7306         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7307 }
7308
7309 /**
7310  * mono_get_reflection_missing_object:
7311  * @domain: Domain where the object lives
7312  *
7313  * Returns the System.Reflection.Missing.Value singleton object
7314  * (of type System.Reflection.Missing).
7315  *
7316  * Used as the value for ParameterInfo.DefaultValue when Optional
7317  * is present
7318  */
7319 static MonoObject *
7320 mono_get_reflection_missing_object (MonoDomain *domain)
7321 {
7322         MonoObject *obj;
7323         static MonoClassField *missing_value_field = NULL;
7324         
7325         if (!missing_value_field) {
7326                 MonoClass *missing_klass;
7327                 missing_klass = mono_class_get_missing_class ();
7328                 mono_class_init (missing_klass);
7329                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7330                 g_assert (missing_value_field);
7331         }
7332         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7333         g_assert (obj);
7334         return obj;
7335 }
7336
7337 static MonoObject*
7338 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7339 {
7340         if (!*dbnull)
7341                 *dbnull = mono_get_dbnull_object (domain);
7342         return *dbnull;
7343 }
7344
7345 static MonoObject*
7346 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7347 {
7348         if (!*reflection_missing)
7349                 *reflection_missing = mono_get_reflection_missing_object (domain);
7350         return *reflection_missing;
7351 }
7352
7353 /*
7354  * mono_param_get_objects:
7355  * @domain: an app domain
7356  * @method: a method
7357  *
7358  * Return an System.Reflection.ParameterInfo array object representing the parameters
7359  * in the method @method.
7360  */
7361 MonoArray*
7362 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7363 {
7364         static MonoClass *System_Reflection_ParameterInfo;
7365         static MonoClass *System_Reflection_ParameterInfo_array;
7366         MonoArray *res = NULL;
7367         MonoReflectionMethod *member = NULL;
7368         MonoReflectionParameter *param = NULL;
7369         char **names = NULL, **blobs = NULL;
7370         guint32 *types = NULL;
7371         MonoType *type = NULL;
7372         MonoObject *dbnull = NULL;
7373         MonoObject *missing = NULL;
7374         MonoMarshalSpec **mspecs = NULL;
7375         MonoMethodSignature *sig = NULL;
7376         MonoVTable *pinfo_vtable;
7377         MonoReflectionType *rt;
7378         int i;
7379
7380         mono_error_init (error);
7381         
7382         if (!System_Reflection_ParameterInfo_array) {
7383                 MonoClass *klass;
7384
7385                 klass = mono_class_get_mono_parameter_info_class ();
7386
7387                 mono_memory_barrier ();
7388                 System_Reflection_ParameterInfo = klass; 
7389
7390         
7391                 klass = mono_array_class_get (klass, 1);
7392                 mono_memory_barrier ();
7393                 System_Reflection_ParameterInfo_array = klass;
7394         }
7395
7396         sig = mono_method_signature_checked (method, error);
7397         if (!mono_error_ok (error))
7398                 goto leave;
7399
7400         if (!sig->param_count) {
7401                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7402                 if (!res)
7403                         goto leave;
7404
7405                 return res;
7406         }
7407
7408         /* Note: the cache is based on the address of the signature into the method
7409          * since we already cache MethodInfos with the method as keys.
7410          */
7411         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7412
7413         member = mono_method_get_object_checked (domain, method, refclass, error);
7414         if (!member)
7415                 goto leave;
7416         names = g_new (char *, sig->param_count);
7417         mono_method_get_param_names (method, (const char **) names);
7418
7419         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7420         mono_method_get_marshal_info (method, mspecs);
7421
7422         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7423         if (!res)
7424                 goto leave;
7425
7426         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7427         for (i = 0; i < sig->param_count; ++i) {
7428                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7429                 if (!param)
7430                         goto leave;
7431
7432                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7433                 if (!rt)
7434                         goto leave;
7435
7436                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7437
7438                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7439
7440                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7441
7442                 param->PositionImpl = i;
7443                 param->AttrsImpl = sig->params [i]->attrs;
7444
7445                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7446                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7447                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7448                         else
7449                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7450                 } else {
7451
7452                         if (!blobs) {
7453                                 blobs = g_new0 (char *, sig->param_count);
7454                                 types = g_new0 (guint32, sig->param_count);
7455                                 get_default_param_value_blobs (method, blobs, types); 
7456                         }
7457
7458                         /* Build MonoType for the type from the Constant Table */
7459                         if (!type)
7460                                 type = g_new0 (MonoType, 1);
7461                         type->type = (MonoTypeEnum)types [i];
7462                         type->data.klass = NULL;
7463                         if (types [i] == MONO_TYPE_CLASS)
7464                                 type->data.klass = mono_defaults.object_class;
7465                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7466                                 /* For enums, types [i] contains the base type */
7467
7468                                         type->type = MONO_TYPE_VALUETYPE;
7469                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7470                         } else
7471                                 type->data.klass = mono_class_from_mono_type (type);
7472
7473                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7474                         if (!is_ok (error))
7475                                 goto leave;
7476                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7477
7478                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7479                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7480                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7481                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7482                                 else
7483                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7484                         }
7485                         
7486                 }
7487
7488                 if (mspecs [i + 1]) {
7489                         MonoReflectionMarshalAsAttribute* mobj;
7490                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7491                         if (!mobj)
7492                                 goto leave;
7493                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7494                 }
7495                 
7496                 mono_array_setref (res, i, param);
7497         }
7498
7499 leave:
7500         g_free (names);
7501         g_free (blobs);
7502         g_free (types);
7503         g_free (type);
7504
7505         if (sig) {
7506                 for (i = sig->param_count; i >= 0; i--) {
7507                         if (mspecs [i])
7508                                 mono_metadata_free_marshal_spec (mspecs [i]);
7509                 }
7510         }
7511         g_free (mspecs);
7512
7513         if (!is_ok (error))
7514                 return NULL;
7515         
7516         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7517 }
7518
7519 MonoArray*
7520 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7521 {
7522         MonoError error;
7523         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7524         mono_error_assert_ok (&error);
7525         return result;
7526 }
7527
7528 /*
7529  * mono_method_body_get_object:
7530  * @domain: an app domain
7531  * @method: a method
7532  *
7533  * Return an System.Reflection.MethodBody object representing the method @method.
7534  */
7535 MonoReflectionMethodBody*
7536 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7537 {
7538         MonoError error;
7539         MonoReflectionMethodBody *ret;
7540         MonoMethodHeader *header;
7541         MonoImage *image;
7542         MonoReflectionType *rt;
7543         guint32 method_rva, local_var_sig_token;
7544     char *ptr;
7545         unsigned char format, flags;
7546         int i;
7547
7548         /* for compatibility with .net */
7549     if (method_is_dynamic (method))
7550         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7551
7552         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7553
7554         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7555                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7556             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7557                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7558             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7559                 return NULL;
7560
7561         image = method->klass->image;
7562         header = mono_method_get_header (method);
7563
7564         if (!image_is_dynamic (image)) {
7565                 /* Obtain local vars signature token */
7566                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7567                 ptr = mono_image_rva_map (image, method_rva);
7568                 flags = *(const unsigned char *) ptr;
7569                 format = flags & METHOD_HEADER_FORMAT_MASK;
7570                 switch (format){
7571                 case METHOD_HEADER_TINY_FORMAT:
7572                         local_var_sig_token = 0;
7573                         break;
7574                 case METHOD_HEADER_FAT_FORMAT:
7575                         ptr += 2;
7576                         ptr += 2;
7577                         ptr += 4;
7578                         local_var_sig_token = read32 (ptr);
7579                         break;
7580                 default:
7581                         g_assert_not_reached ();
7582                 }
7583         } else
7584                 local_var_sig_token = 0; //FIXME
7585
7586         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7587         mono_error_raise_exception (&error); /* FIXME don't raise here */
7588
7589         ret->init_locals = header->init_locals;
7590         ret->max_stack = header->max_stack;
7591         ret->local_var_sig_token = local_var_sig_token;
7592         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7593         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7594
7595         /* Locals */
7596         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7597         for (i = 0; i < header->num_locals; ++i) {
7598                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7599                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7600
7601                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7602                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7603
7604                 MONO_OBJECT_SETREF (info, local_type, rt);
7605
7606                 info->is_pinned = header->locals [i]->pinned;
7607                 info->local_index = i;
7608                 mono_array_setref (ret->locals, i, info);
7609         }
7610
7611         /* Exceptions */
7612         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7613         for (i = 0; i < header->num_clauses; ++i) {
7614                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7615                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7616                 MonoExceptionClause *clause = &header->clauses [i];
7617
7618                 info->flags = clause->flags;
7619                 info->try_offset = clause->try_offset;
7620                 info->try_length = clause->try_len;
7621                 info->handler_offset = clause->handler_offset;
7622                 info->handler_length = clause->handler_len;
7623                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7624                         info->filter_offset = clause->data.filter_offset;
7625                 else if (clause->data.catch_class) {
7626                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7627                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7628
7629                         MONO_OBJECT_SETREF (info, catch_type, rt);
7630                 }
7631
7632                 mono_array_setref (ret->clauses, i, info);
7633         }
7634
7635         mono_metadata_free_mh (header);
7636         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7637         return ret;
7638 }
7639
7640 /**
7641  * mono_get_dbnull_object:
7642  * @domain: Domain where the object lives
7643  *
7644  * Returns the System.DBNull.Value singleton object
7645  *
7646  * Used as the value for ParameterInfo.DefaultValue 
7647  */
7648 MonoObject *
7649 mono_get_dbnull_object (MonoDomain *domain)
7650 {
7651         MonoObject *obj;
7652         static MonoClassField *dbnull_value_field = NULL;
7653         
7654         if (!dbnull_value_field) {
7655                 MonoClass *dbnull_klass;
7656                 dbnull_klass = mono_class_get_dbnull_class ();
7657                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7658                 g_assert (dbnull_value_field);
7659         }
7660         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7661         g_assert (obj);
7662         return obj;
7663 }
7664
7665 static void
7666 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7667 {
7668         guint32 param_index, i, lastp, crow = 0;
7669         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7670         gint32 idx;
7671
7672         MonoClass *klass = method->klass;
7673         MonoImage *image = klass->image;
7674         MonoMethodSignature *methodsig = mono_method_signature (method);
7675
7676         MonoTableInfo *constt;
7677         MonoTableInfo *methodt;
7678         MonoTableInfo *paramt;
7679
7680         if (!methodsig->param_count)
7681                 return;
7682
7683         mono_class_init (klass);
7684
7685         if (image_is_dynamic (klass->image)) {
7686                 MonoReflectionMethodAux *aux;
7687                 if (method->is_inflated)
7688                         method = ((MonoMethodInflated*)method)->declaring;
7689                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7690                 if (aux && aux->param_defaults) {
7691                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7692                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7693                 }
7694                 return;
7695         }
7696
7697         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7698         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7699         constt = &image->tables [MONO_TABLE_CONSTANT];
7700
7701         idx = mono_method_get_index (method) - 1;
7702         g_assert (idx != -1);
7703
7704         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7705         if (idx + 1 < methodt->rows)
7706                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7707         else
7708                 lastp = paramt->rows + 1;
7709
7710         for (i = param_index; i < lastp; ++i) {
7711                 guint32 paramseq;
7712
7713                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7714                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7715
7716                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7717                         continue;
7718
7719                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7720                 if (!crow) {
7721                         continue;
7722                 }
7723         
7724                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7725                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7726                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7727         }
7728
7729         return;
7730 }
7731
7732 MonoObject *
7733 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
7734 {
7735         void *retval;
7736         MonoClass *klass;
7737         MonoObject *object;
7738         MonoType *basetype = type;
7739
7740         mono_error_init (error);
7741
7742         if (!blob)
7743                 return NULL;
7744         
7745         klass = mono_class_from_mono_type (type);
7746         if (klass->valuetype) {
7747                 object = mono_object_new_checked (domain, klass, error);
7748                 return_val_if_nok (error, NULL);
7749                 retval = ((gchar *) object + sizeof (MonoObject));
7750                 if (klass->enumtype)
7751                         basetype = mono_class_enum_basetype (klass);
7752         } else {
7753                 retval = &object;
7754         }
7755                         
7756         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7757                 return object;
7758         else
7759                 return NULL;
7760 }
7761
7762 static int
7763 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7764         int found_sep;
7765         char *s;
7766         gboolean quoted = FALSE;
7767
7768         memset (assembly, 0, sizeof (MonoAssemblyName));
7769         assembly->culture = "";
7770         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7771
7772         if (*p == '"') {
7773                 quoted = TRUE;
7774                 p++;
7775         }
7776         assembly->name = p;
7777         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7778                 p++;
7779         if (quoted) {
7780                 if (*p != '"')
7781                         return 1;
7782                 *p = 0;
7783                 p++;
7784         }
7785         if (*p != ',')
7786                 return 1;
7787         *p = 0;
7788         /* Remove trailing whitespace */
7789         s = p - 1;
7790         while (*s && g_ascii_isspace (*s))
7791                 *s-- = 0;
7792         p ++;
7793         while (g_ascii_isspace (*p))
7794                 p++;
7795         while (*p) {
7796                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7797                         p += 8;
7798                         assembly->major = strtoul (p, &s, 10);
7799                         if (s == p || *s != '.')
7800                                 return 1;
7801                         p = ++s;
7802                         assembly->minor = strtoul (p, &s, 10);
7803                         if (s == p || *s != '.')
7804                                 return 1;
7805                         p = ++s;
7806                         assembly->build = strtoul (p, &s, 10);
7807                         if (s == p || *s != '.')
7808                                 return 1;
7809                         p = ++s;
7810                         assembly->revision = strtoul (p, &s, 10);
7811                         if (s == p)
7812                                 return 1;
7813                         p = s;
7814                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7815                         p += 8;
7816                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7817                                 assembly->culture = "";
7818                                 p += 7;
7819                         } else {
7820                                 assembly->culture = p;
7821                                 while (*p && *p != ',') {
7822                                         p++;
7823                                 }
7824                         }
7825                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7826                         p += 15;
7827                         if (strncmp (p, "null", 4) == 0) {
7828                                 p += 4;
7829                         } else {
7830                                 int len;
7831                                 gchar *start = p;
7832                                 while (*p && *p != ',') {
7833                                         p++;
7834                                 }
7835                                 len = (p - start + 1);
7836                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7837                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7838                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7839                         }
7840                 } else {
7841                         while (*p && *p != ',')
7842                                 p++;
7843                 }
7844                 found_sep = 0;
7845                 while (g_ascii_isspace (*p) || *p == ',') {
7846                         *p++ = 0;
7847                         found_sep = 1;
7848                         continue;
7849                 }
7850                 /* failed */
7851                 if (!found_sep)
7852                         return 1;
7853         }
7854
7855         return 0;
7856 }
7857
7858 /*
7859  * mono_reflection_parse_type:
7860  * @name: type name
7861  *
7862  * Parse a type name as accepted by the GetType () method and output the info
7863  * extracted in the info structure.
7864  * the name param will be mangled, so, make a copy before passing it to this function.
7865  * The fields in info will be valid until the memory pointed to by name is valid.
7866  *
7867  * See also mono_type_get_name () below.
7868  *
7869  * Returns: 0 on parse error.
7870  */
7871 static int
7872 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7873                              MonoTypeNameParse *info)
7874 {
7875         char *start, *p, *w, *last_point, *startn;
7876         int in_modifiers = 0;
7877         int isbyref = 0, rank = 0, isptr = 0;
7878
7879         start = p = w = name;
7880
7881         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7882         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7883         info->name = info->name_space = NULL;
7884         info->nested = NULL;
7885         info->modifiers = NULL;
7886         info->type_arguments = NULL;
7887
7888         /* last_point separates the namespace from the name */
7889         last_point = NULL;
7890         /* Skips spaces */
7891         while (*p == ' ') p++, start++, w++, name++;
7892
7893         while (*p) {
7894                 switch (*p) {
7895                 case '+':
7896                         *p = 0; /* NULL terminate the name */
7897                         startn = p + 1;
7898                         info->nested = g_list_append (info->nested, startn);
7899                         /* we have parsed the nesting namespace + name */
7900                         if (info->name)
7901                                 break;
7902                         if (last_point) {
7903                                 info->name_space = start;
7904                                 *last_point = 0;
7905                                 info->name = last_point + 1;
7906                         } else {
7907                                 info->name_space = (char *)"";
7908                                 info->name = start;
7909                         }
7910                         break;
7911                 case '.':
7912                         last_point = p;
7913                         break;
7914                 case '\\':
7915                         ++p;
7916                         break;
7917                 case '&':
7918                 case '*':
7919                 case '[':
7920                 case ',':
7921                 case ']':
7922                         in_modifiers = 1;
7923                         break;
7924                 default:
7925                         break;
7926                 }
7927                 if (in_modifiers)
7928                         break;
7929                 // *w++ = *p++;
7930                 p++;
7931         }
7932         
7933         if (!info->name) {
7934                 if (last_point) {
7935                         info->name_space = start;
7936                         *last_point = 0;
7937                         info->name = last_point + 1;
7938                 } else {
7939                         info->name_space = (char *)"";
7940                         info->name = start;
7941                 }
7942         }
7943         while (*p) {
7944                 switch (*p) {
7945                 case '&':
7946                         if (isbyref) /* only one level allowed by the spec */
7947                                 return 0;
7948                         isbyref = 1;
7949                         isptr = 0;
7950                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7951                         *p++ = 0;
7952                         break;
7953                 case '*':
7954                         if (isbyref) /* pointer to ref not okay */
7955                                 return 0;
7956                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7957                         isptr = 1;
7958                         *p++ = 0;
7959                         break;
7960                 case '[':
7961                         if (isbyref) /* array of ref and generic ref are not okay */
7962                                 return 0;
7963                         //Decide if it's an array of a generic argument list
7964                         *p++ = 0;
7965
7966                         if (!*p) //XXX test
7967                                 return 0;
7968                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7969                                 isptr = 0;
7970                                 rank = 1;
7971                                 while (*p) {
7972                                         if (*p == ']')
7973                                                 break;
7974                                         if (*p == ',')
7975                                                 rank++;
7976                                         else if (*p == '*') /* '*' means unknown lower bound */
7977                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7978                                         else
7979                                                 return 0;
7980                                         ++p;
7981                                 }
7982                                 if (*p++ != ']')
7983                                         return 0;
7984                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7985                         } else {
7986                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7987                                         return 0;
7988                                 isptr = 0;
7989                                 info->type_arguments = g_ptr_array_new ();
7990                                 while (*p) {
7991                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7992                                         gboolean fqname = FALSE;
7993
7994                                         g_ptr_array_add (info->type_arguments, subinfo);
7995
7996                                         while (*p == ' ') p++;
7997                                         if (*p == '[') {
7998                                                 p++;
7999                                                 fqname = TRUE;
8000                                         }
8001
8002                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8003                                                 return 0;
8004
8005                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8006                                         if (fqname && (*p != ']')) {
8007                                                 char *aname;
8008
8009                                                 if (*p != ',')
8010                                                         return 0;
8011                                                 *p++ = 0;
8012
8013                                                 aname = p;
8014                                                 while (*p && (*p != ']'))
8015                                                         p++;
8016
8017                                                 if (*p != ']')
8018                                                         return 0;
8019
8020                                                 *p++ = 0;
8021                                                 while (*aname) {
8022                                                         if (g_ascii_isspace (*aname)) {
8023                                                                 ++aname;
8024                                                                 continue;
8025                                                         }
8026                                                         break;
8027                                                 }
8028                                                 if (!*aname ||
8029                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8030                                                         return 0;
8031                                         } else if (fqname && (*p == ']')) {
8032                                                 *p++ = 0;
8033                                         }
8034                                         if (*p == ']') {
8035                                                 *p++ = 0;
8036                                                 break;
8037                                         } else if (!*p) {
8038                                                 return 0;
8039                                         }
8040                                         *p++ = 0;
8041                                 }
8042                         }
8043                         break;
8044                 case ']':
8045                         if (is_recursed)
8046                                 goto end;
8047                         return 0;
8048                 case ',':
8049                         if (is_recursed)
8050                                 goto end;
8051                         *p++ = 0;
8052                         while (*p) {
8053                                 if (g_ascii_isspace (*p)) {
8054                                         ++p;
8055                                         continue;
8056                                 }
8057                                 break;
8058                         }
8059                         if (!*p)
8060                                 return 0; /* missing assembly name */
8061                         if (!assembly_name_to_aname (&info->assembly, p))
8062                                 return 0;
8063                         break;
8064                 default:
8065                         return 0;
8066                 }
8067                 if (info->assembly.name)
8068                         break;
8069         }
8070         // *w = 0; /* terminate class name */
8071  end:
8072         if (!info->name || !*info->name)
8073                 return 0;
8074         if (endptr)
8075                 *endptr = p;
8076         /* add other consistency checks */
8077         return 1;
8078 }
8079
8080
8081 /**
8082  * mono_identifier_unescape_type_name_chars:
8083  * @identifier: the display name of a mono type
8084  *
8085  * Returns:
8086  *  The name in internal form, that is without escaping backslashes.
8087  *
8088  *  The string is modified in place!
8089  */
8090 char*
8091 mono_identifier_unescape_type_name_chars(char* identifier)
8092 {
8093         char *w, *r;
8094         if (!identifier)
8095                 return NULL;
8096         for (w = r = identifier; *r != 0; r++)
8097         {
8098                 char c = *r;
8099                 if (c == '\\') {
8100                         r++;
8101                         if (*r == 0)
8102                                 break;
8103                         c = *r;
8104                 }
8105                 *w = c;
8106                 w++;
8107         }
8108         if (w != r)
8109                 *w = 0;
8110         return identifier;
8111 }
8112
8113 void
8114 mono_identifier_unescape_info (MonoTypeNameParse* info);
8115
8116 static void
8117 unescape_each_type_argument(void* data, void* user_data)
8118 {
8119         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8120         mono_identifier_unescape_info (info);
8121 }
8122
8123 static void
8124 unescape_each_nested_name (void* data, void* user_data)
8125 {
8126         char* nested_name = (char*) data;
8127         mono_identifier_unescape_type_name_chars(nested_name);
8128 }
8129
8130 /**
8131  * mono_identifier_unescape_info:
8132  *
8133  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8134  *
8135  * Returns: nothing.
8136  *
8137  * Destructively updates the info by unescaping the identifiers that
8138  * comprise the type namespace, name, nested types (if any) and
8139  * generic type arguments (if any).
8140  *
8141  * The resulting info has the names in internal form.
8142  *
8143  */
8144 void
8145 mono_identifier_unescape_info (MonoTypeNameParse *info)
8146 {
8147         if (!info)
8148                 return;
8149         mono_identifier_unescape_type_name_chars(info->name_space);
8150         mono_identifier_unescape_type_name_chars(info->name);
8151         // but don't escape info->assembly
8152         if (info->type_arguments)
8153                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8154         if (info->nested)
8155                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8156 }
8157
8158 int
8159 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8160 {
8161         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8162         if (ok) {
8163                 mono_identifier_unescape_info (info);
8164         }
8165         return ok;
8166 }
8167
8168 static MonoType*
8169 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8170 {
8171         gboolean type_resolve = FALSE;
8172         MonoType *type;
8173         MonoImage *rootimage = image;
8174
8175         if (info->assembly.name) {
8176                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8177                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8178                         /* 
8179                          * This could happen in the AOT compiler case when the search hook is not
8180                          * installed.
8181                          */
8182                         assembly = image->assembly;
8183                 if (!assembly) {
8184                         /* then we must load the assembly ourselve - see #60439 */
8185                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8186                         if (!assembly)
8187                                 return NULL;
8188                 }
8189                 image = assembly->image;
8190         } else if (!image) {
8191                 image = mono_defaults.corlib;
8192         }
8193
8194         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8195         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8196                 image = mono_defaults.corlib;
8197                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8198         }
8199
8200         return type;
8201 }
8202
8203 /**
8204  * mono_reflection_get_type_internal:
8205  *
8206  * Returns: may return NULL on success, sets error on failure.
8207  */
8208 static MonoType*
8209 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8210 {
8211         MonoClass *klass;
8212         GList *mod;
8213         int modval;
8214         gboolean bounded = FALSE;
8215         
8216         mono_error_init (error);
8217         if (!image)
8218                 image = mono_defaults.corlib;
8219
8220         if (!rootimage)
8221                 rootimage = mono_defaults.corlib;
8222
8223         if (ignorecase)
8224                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8225         else
8226                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8227
8228         if (!klass)
8229                 return NULL;
8230
8231         for (mod = info->nested; mod; mod = mod->next) {
8232                 gpointer iter = NULL;
8233                 MonoClass *parent;
8234
8235                 parent = klass;
8236                 mono_class_init (parent);
8237
8238                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8239                         char *lastp;
8240                         char *nested_name, *nested_nspace;
8241                         gboolean match = TRUE;
8242
8243                         lastp = strrchr ((const char *)mod->data, '.');
8244                         if (lastp) {
8245                                 /* Nested classes can have namespaces */
8246                                 int nspace_len;
8247
8248                                 nested_name = g_strdup (lastp + 1);
8249                                 nspace_len = lastp - (char*)mod->data;
8250                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8251                                 memcpy (nested_nspace, mod->data, nspace_len);
8252                                 nested_nspace [nspace_len] = '\0';
8253
8254                         } else {
8255                                 nested_name = (char *)mod->data;
8256                                 nested_nspace = NULL;
8257                         }
8258
8259                         if (nested_nspace) {
8260                                 if (ignorecase) {
8261                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8262                                                 match = FALSE;
8263                                 } else {
8264                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8265                                                 match = FALSE;
8266                                 }
8267                         }
8268                         if (match) {
8269                                 if (ignorecase) {
8270                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8271                                                 match = FALSE;
8272                                 } else {
8273                                         if (strcmp (klass->name, nested_name) != 0)
8274                                                 match = FALSE;
8275                                 }
8276                         }
8277                         if (lastp) {
8278                                 g_free (nested_name);
8279                                 g_free (nested_nspace);
8280                         }
8281                         if (match)
8282                                 break;
8283                 }
8284
8285                 if (!klass)
8286                         break;
8287         }
8288         if (!klass)
8289                 return NULL;
8290
8291         if (info->type_arguments) {
8292                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8293                 MonoReflectionType *the_type;
8294                 MonoType *instance;
8295                 int i;
8296
8297                 for (i = 0; i < info->type_arguments->len; i++) {
8298                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8299
8300                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8301                         if (!type_args [i]) {
8302                                 g_free (type_args);
8303                                 return NULL;
8304                         }
8305                 }
8306
8307                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8308                 if (!the_type)
8309                         return NULL;
8310
8311                 instance = mono_reflection_bind_generic_parameters (
8312                         the_type, info->type_arguments->len, type_args);
8313
8314                 g_free (type_args);
8315                 if (!instance)
8316                         return NULL;
8317
8318                 klass = mono_class_from_mono_type (instance);
8319         }
8320
8321         for (mod = info->modifiers; mod; mod = mod->next) {
8322                 modval = GPOINTER_TO_UINT (mod->data);
8323                 if (!modval) { /* byref: must be last modifier */
8324                         return &klass->this_arg;
8325                 } else if (modval == -1) {
8326                         klass = mono_ptr_class_get (&klass->byval_arg);
8327                 } else if (modval == -2) {
8328                         bounded = TRUE;
8329                 } else { /* array rank */
8330                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8331                 }
8332         }
8333
8334         return &klass->byval_arg;
8335 }
8336
8337 /*
8338  * mono_reflection_get_type:
8339  * @image: a metadata context
8340  * @info: type description structure
8341  * @ignorecase: flag for case-insensitive string compares
8342  * @type_resolve: whenever type resolve was already tried
8343  *
8344  * Build a MonoType from the type description in @info.
8345  * 
8346  */
8347
8348 MonoType*
8349 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8350         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
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)
8396 {
8397         MonoError error;
8398         MonoType *type;
8399         MonoReflectionAssembly *assembly;
8400         GString *fullName;
8401         GList *mod;
8402
8403         if (image && image_is_dynamic (image))
8404                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8405         else {
8406                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8407         }
8408         if (!mono_error_ok (&error))
8409                 mono_error_raise_exception (&error); /* FIXME don't raise here */
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         mono_error_raise_exception (&error); /* FIXME don't raise here */
8434
8435         if (assembly) {
8436                 if (assembly_is_dynamic (assembly->assembly))
8437                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8438                                                                           info, ignorecase, &error);
8439                 else
8440                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8441                                                                   info, ignorecase, &error);
8442         }
8443         g_string_free (fullName, TRUE);
8444         if (!mono_error_ok (&error))
8445                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8446         return type;
8447 }
8448
8449 void
8450 mono_reflection_free_type_info (MonoTypeNameParse *info)
8451 {
8452         g_list_free (info->modifiers);
8453         g_list_free (info->nested);
8454
8455         if (info->type_arguments) {
8456                 int i;
8457
8458                 for (i = 0; i < info->type_arguments->len; i++) {
8459                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8460
8461                         mono_reflection_free_type_info (subinfo);
8462                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8463                         g_free (subinfo);
8464                 }
8465
8466                 g_ptr_array_free (info->type_arguments, TRUE);
8467         }
8468 }
8469
8470 /*
8471  * mono_reflection_type_from_name:
8472  * @name: type name.
8473  * @image: a metadata context (can be NULL).
8474  *
8475  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8476  * it defaults to get the type from @image or, if @image is NULL or loading
8477  * from it fails, uses corlib.
8478  * 
8479  */
8480 MonoType*
8481 mono_reflection_type_from_name (char *name, MonoImage *image)
8482 {
8483         MonoType *type = NULL;
8484         MonoTypeNameParse info;
8485         char *tmp;
8486
8487         /* Make a copy since parse_type modifies its argument */
8488         tmp = g_strdup (name);
8489         
8490         /*g_print ("requested type %s\n", str);*/
8491         if (mono_reflection_parse_type (tmp, &info)) {
8492                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8493         }
8494
8495         g_free (tmp);
8496         mono_reflection_free_type_info (&info);
8497         return type;
8498 }
8499
8500 /*
8501  * mono_reflection_get_token:
8502  *
8503  *   Return the metadata token of OBJ which should be an object
8504  * representing a metadata element.
8505  */
8506 guint32
8507 mono_reflection_get_token (MonoObject *obj)
8508 {
8509         MonoClass *klass;
8510         guint32 token = 0;
8511
8512         klass = obj->vtable->klass;
8513
8514         if (strcmp (klass->name, "MethodBuilder") == 0) {
8515                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8516
8517                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8518         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8519                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8520
8521                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8522         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8523                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8524
8525                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8526         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8527                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8528                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8529         } else if (strcmp (klass->name, "MonoType") == 0) {
8530                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8531                 MonoClass *mc = mono_class_from_mono_type (type);
8532                 if (!mono_class_init (mc))
8533                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8534
8535                 token = mc->type_token;
8536         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8537                    strcmp (klass->name, "MonoMethod") == 0 ||
8538                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8539                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8540                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8541                 if (m->method->is_inflated) {
8542                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8543                         return inflated->declaring->token;
8544                 } else {
8545                         token = m->method->token;
8546                 }
8547         } else if (strcmp (klass->name, "MonoField") == 0) {
8548                 MonoReflectionField *f = (MonoReflectionField*)obj;
8549
8550                 if (is_field_on_inst (f->field)) {
8551                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8552
8553                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8554                                 int field_index = f->field - dgclass->fields;
8555                                 MonoObject *obj;
8556
8557                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8558                                 obj = dgclass->field_objects [field_index];
8559                                 return mono_reflection_get_token (obj);
8560                         }
8561                 }
8562                 token = mono_class_get_field_token (f->field);
8563         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8564                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8565
8566                 token = mono_class_get_property_token (p->property);
8567         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8568                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8569
8570                 token = mono_class_get_event_token (p->event);
8571         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8572                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8573                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8574                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8575
8576                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8577         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8578                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8579
8580                 token = m->token;
8581         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8582                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8583         } else {
8584                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8585                 MonoException *ex = mono_get_exception_not_implemented (msg);
8586                 g_free (msg);
8587                 mono_raise_exception (ex);
8588         }
8589
8590         return token;
8591 }
8592
8593 static MonoClass*
8594 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8595 {
8596         char *n;
8597         MonoType *t;
8598         int slen = mono_metadata_decode_value (p, &p);
8599
8600         mono_error_init (error);
8601
8602         n = (char *)g_memdup (p, slen + 1);
8603         n [slen] = 0;
8604         t = mono_reflection_type_from_name (n, image);
8605         if (!t) {
8606                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8607                 /* We don't free n, it's consumed by mono_error */
8608                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8609                 return NULL;
8610         }
8611         g_free (n);
8612         p += slen;
8613         *end = p;
8614         return mono_class_from_mono_type (t);
8615 }
8616
8617 static void*
8618 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8619 {
8620         int slen, type = t->type;
8621         MonoClass *tklass = t->data.klass;
8622
8623         mono_error_init (error);
8624
8625 handle_enum:
8626         switch (type) {
8627         case MONO_TYPE_U1:
8628         case MONO_TYPE_I1:
8629         case MONO_TYPE_BOOLEAN: {
8630                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8631                 *bval = *p;
8632                 *end = p + 1;
8633                 return bval;
8634         }
8635         case MONO_TYPE_CHAR:
8636         case MONO_TYPE_U2:
8637         case MONO_TYPE_I2: {
8638                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8639                 *val = read16 (p);
8640                 *end = p + 2;
8641                 return val;
8642         }
8643 #if SIZEOF_VOID_P == 4
8644         case MONO_TYPE_U:
8645         case MONO_TYPE_I:
8646 #endif
8647         case MONO_TYPE_R4:
8648         case MONO_TYPE_U4:
8649         case MONO_TYPE_I4: {
8650                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8651                 *val = read32 (p);
8652                 *end = p + 4;
8653                 return val;
8654         }
8655 #if SIZEOF_VOID_P == 8
8656         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8657         case MONO_TYPE_I:
8658 #endif
8659         case MONO_TYPE_U8:
8660         case MONO_TYPE_I8: {
8661                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8662                 *val = read64 (p);
8663                 *end = p + 8;
8664                 return val;
8665         }
8666         case MONO_TYPE_R8: {
8667                 double *val = (double *)g_malloc (sizeof (double));
8668                 readr8 (p, val);
8669                 *end = p + 8;
8670                 return val;
8671         }
8672         case MONO_TYPE_VALUETYPE:
8673                 if (t->data.klass->enumtype) {
8674                         type = mono_class_enum_basetype (t->data.klass)->type;
8675                         goto handle_enum;
8676                 } else {
8677                         MonoClass *k =  t->data.klass;
8678                         
8679                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8680                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8681                                 *val = read64 (p);
8682                                 *end = p + 8;
8683                                 return val;
8684                         }
8685                 }
8686                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8687                 break;
8688                 
8689         case MONO_TYPE_STRING:
8690                 if (*p == (char)0xFF) {
8691                         *end = p + 1;
8692                         return NULL;
8693                 }
8694                 slen = mono_metadata_decode_value (p, &p);
8695                 *end = p + slen;
8696                 return mono_string_new_len (mono_domain_get (), p, slen);
8697         case MONO_TYPE_CLASS: {
8698                 MonoReflectionType *rt;
8699                 char *n;
8700                 MonoType *t;
8701                 if (*p == (char)0xFF) {
8702                         *end = p + 1;
8703                         return NULL;
8704                 }
8705 handle_type:
8706                 slen = mono_metadata_decode_value (p, &p);
8707                 n = (char *)g_memdup (p, slen + 1);
8708                 n [slen] = 0;
8709                 t = mono_reflection_type_from_name (n, image);
8710                 if (!t) {
8711                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8712                         /* We don't free n, it's consumed by mono_error */
8713                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8714                         return NULL;
8715                 }
8716                 g_free (n);
8717                 *end = p + slen;
8718
8719                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8720                 if (!mono_error_ok (error))
8721                         return NULL;
8722
8723                 return rt;
8724         }
8725         case MONO_TYPE_OBJECT: {
8726                 char subt = *p++;
8727                 MonoObject *obj;
8728                 MonoClass *subc = NULL;
8729                 void *val;
8730
8731                 if (subt == 0x50) {
8732                         goto handle_type;
8733                 } else if (subt == 0x0E) {
8734                         type = MONO_TYPE_STRING;
8735                         goto handle_enum;
8736                 } else if (subt == 0x1D) {
8737                         MonoType simple_type = {{0}};
8738                         int etype = *p;
8739                         p ++;
8740
8741                         type = MONO_TYPE_SZARRAY;
8742                         if (etype == 0x50) {
8743                                 tklass = mono_defaults.systemtype_class;
8744                         } else if (etype == 0x55) {
8745                                 tklass = load_cattr_enum_type (image, p, &p, error);
8746                                 if (!mono_error_ok (error))
8747                                         return NULL;
8748                         } else {
8749                                 if (etype == 0x51)
8750                                         /* See Partition II, Appendix B3 */
8751                                         etype = MONO_TYPE_OBJECT;
8752                                 simple_type.type = (MonoTypeEnum)etype;
8753                                 tklass = mono_class_from_mono_type (&simple_type);
8754                         }
8755                         goto handle_enum;
8756                 } else if (subt == 0x55) {
8757                         char *n;
8758                         MonoType *t;
8759                         slen = mono_metadata_decode_value (p, &p);
8760                         n = (char *)g_memdup (p, slen + 1);
8761                         n [slen] = 0;
8762                         t = mono_reflection_type_from_name (n, image);
8763                         if (!t) {
8764                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8765                                 /* We don't free n, it's consumed by mono_error */
8766                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8767                                 return NULL;
8768                         }
8769                         g_free (n);
8770                         p += slen;
8771                         subc = mono_class_from_mono_type (t);
8772                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8773                         MonoType simple_type = {{0}};
8774                         simple_type.type = (MonoTypeEnum)subt;
8775                         subc = mono_class_from_mono_type (&simple_type);
8776                 } else {
8777                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8778                 }
8779                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8780                 obj = NULL;
8781                 if (mono_error_ok (error)) {
8782                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8783                         g_assert (!subc->has_references);
8784                         if (mono_error_ok (error))
8785                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8786                 }
8787
8788                 g_free (val);
8789                 return obj;
8790         }
8791         case MONO_TYPE_SZARRAY: {
8792                 MonoArray *arr;
8793                 guint32 i, alen, basetype;
8794                 alen = read32 (p);
8795                 p += 4;
8796                 if (alen == 0xffffffff) {
8797                         *end = p;
8798                         return NULL;
8799                 }
8800                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8801                 basetype = tklass->byval_arg.type;
8802                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8803                         basetype = mono_class_enum_basetype (tklass)->type;
8804                 switch (basetype)
8805                 {
8806                         case MONO_TYPE_U1:
8807                         case MONO_TYPE_I1:
8808                         case MONO_TYPE_BOOLEAN:
8809                                 for (i = 0; i < alen; i++) {
8810                                         MonoBoolean val = *p++;
8811                                         mono_array_set (arr, MonoBoolean, i, val);
8812                                 }
8813                                 break;
8814                         case MONO_TYPE_CHAR:
8815                         case MONO_TYPE_U2:
8816                         case MONO_TYPE_I2:
8817                                 for (i = 0; i < alen; i++) {
8818                                         guint16 val = read16 (p);
8819                                         mono_array_set (arr, guint16, i, val);
8820                                         p += 2;
8821                                 }
8822                                 break;
8823                         case MONO_TYPE_R4:
8824                         case MONO_TYPE_U4:
8825                         case MONO_TYPE_I4:
8826                                 for (i = 0; i < alen; i++) {
8827                                         guint32 val = read32 (p);
8828                                         mono_array_set (arr, guint32, i, val);
8829                                         p += 4;
8830                                 }
8831                                 break;
8832                         case MONO_TYPE_R8:
8833                                 for (i = 0; i < alen; i++) {
8834                                         double val;
8835                                         readr8 (p, &val);
8836                                         mono_array_set (arr, double, i, val);
8837                                         p += 8;
8838                                 }
8839                                 break;
8840                         case MONO_TYPE_U8:
8841                         case MONO_TYPE_I8:
8842                                 for (i = 0; i < alen; i++) {
8843                                         guint64 val = read64 (p);
8844                                         mono_array_set (arr, guint64, i, val);
8845                                         p += 8;
8846                                 }
8847                                 break;
8848                         case MONO_TYPE_CLASS:
8849                         case MONO_TYPE_OBJECT:
8850                         case MONO_TYPE_STRING:
8851                         case MONO_TYPE_SZARRAY:
8852                                 for (i = 0; i < alen; i++) {
8853                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8854                                         if (!mono_error_ok (error))
8855                                                 return NULL;
8856                                         mono_array_setref (arr, i, item);
8857                                 }
8858                                 break;
8859                         default:
8860                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8861                 }
8862                 *end=p;
8863                 return arr;
8864         }
8865         default:
8866                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8867         }
8868         return NULL;
8869 }
8870
8871 static MonoObject*
8872 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8873 {
8874         static MonoMethod *ctor;
8875         MonoObject *retval;
8876         void *params [2], *unboxed;
8877
8878         mono_error_init (error);
8879
8880         if (!ctor)
8881                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8882         
8883         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8884         return_val_if_nok (error, NULL);
8885
8886         params [1] = val;
8887         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8888         return_val_if_nok (error, NULL);
8889         unboxed = mono_object_unbox (retval);
8890
8891         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8892         return_val_if_nok (error, NULL);
8893
8894         return retval;
8895 }
8896
8897 static MonoObject*
8898 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8899 {
8900         static MonoMethod *ctor;
8901         MonoObject *retval;
8902         void *unboxed, *params [2];
8903
8904         mono_error_init (error);
8905
8906         if (!ctor)
8907                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8908
8909         params [0] = minfo;
8910         params [1] = typedarg;
8911         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8912         return_val_if_nok (error, NULL);
8913
8914         unboxed = mono_object_unbox (retval);
8915
8916         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8917         return_val_if_nok (error, NULL);
8918
8919         return retval;
8920 }
8921
8922 static gboolean
8923 type_is_reference (MonoType *type)
8924 {
8925         switch (type->type) {
8926         case MONO_TYPE_BOOLEAN:
8927         case MONO_TYPE_CHAR:
8928         case MONO_TYPE_U:
8929         case MONO_TYPE_I:
8930         case MONO_TYPE_U1:
8931         case MONO_TYPE_I1:
8932         case MONO_TYPE_U2:
8933         case MONO_TYPE_I2:
8934         case MONO_TYPE_U4:
8935         case MONO_TYPE_I4:
8936         case MONO_TYPE_U8:
8937         case MONO_TYPE_I8:
8938         case MONO_TYPE_R8:
8939         case MONO_TYPE_R4:
8940         case MONO_TYPE_VALUETYPE:
8941                 return FALSE;
8942         default:
8943                 return TRUE;
8944         }
8945 }
8946
8947 static void
8948 free_param_data (MonoMethodSignature *sig, void **params) {
8949         int i;
8950         for (i = 0; i < sig->param_count; ++i) {
8951                 if (!type_is_reference (sig->params [i]))
8952                         g_free (params [i]);
8953         }
8954 }
8955
8956 /*
8957  * Find the field index in the metadata FieldDef table.
8958  */
8959 static guint32
8960 find_field_index (MonoClass *klass, MonoClassField *field) {
8961         int i;
8962
8963         for (i = 0; i < klass->field.count; ++i) {
8964                 if (field == &klass->fields [i])
8965                         return klass->field.first + 1 + i;
8966         }
8967         return 0;
8968 }
8969
8970 /*
8971  * Find the property index in the metadata Property table.
8972  */
8973 static guint32
8974 find_property_index (MonoClass *klass, MonoProperty *property) {
8975         int i;
8976
8977         for (i = 0; i < klass->ext->property.count; ++i) {
8978                 if (property == &klass->ext->properties [i])
8979                         return klass->ext->property.first + 1 + i;
8980         }
8981         return 0;
8982 }
8983
8984 /*
8985  * Find the event index in the metadata Event table.
8986  */
8987 static guint32
8988 find_event_index (MonoClass *klass, MonoEvent *event) {
8989         int i;
8990
8991         for (i = 0; i < klass->ext->event.count; ++i) {
8992                 if (event == &klass->ext->events [i])
8993                         return klass->ext->event.first + 1 + i;
8994         }
8995         return 0;
8996 }
8997
8998 static MonoObject*
8999 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9000 {
9001         const char *p = (const char*)data;
9002         const char *named;
9003         guint32 i, j, num_named;
9004         MonoObject *attr;
9005         void *params_buf [32];
9006         void **params = NULL;
9007         MonoMethodSignature *sig;
9008         MonoObject *exc = NULL;
9009
9010         mono_error_init (error);
9011
9012         mono_class_init (method->klass);
9013
9014         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9015                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9016                 return NULL;
9017         }
9018
9019         if (len == 0) {
9020                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9021                 if (!mono_error_ok (error)) return NULL;
9022
9023                 mono_runtime_invoke_checked (method, attr, NULL, error);
9024                 if (!mono_error_ok (error))
9025                         return NULL;
9026
9027                 return attr;
9028         }
9029
9030         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9031                 return NULL;
9032
9033         /*g_print ("got attr %s\n", method->klass->name);*/
9034
9035         sig = mono_method_signature (method);
9036         if (sig->param_count < 32) {
9037                 params = params_buf;
9038                 memset (params, 0, sizeof (void*) * sig->param_count);
9039         } else {
9040                 /* Allocate using GC so it gets GC tracking */
9041                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9042         }
9043
9044         /* skip prolog */
9045         p += 2;
9046         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9047                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9048                 if (!mono_error_ok (error))
9049                         goto fail;
9050         }
9051
9052         named = p;
9053         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9054         if (!mono_error_ok (error)) goto fail;
9055
9056         mono_runtime_try_invoke (method, attr, params, &exc, error);
9057         if (!mono_error_ok (error))
9058                 goto fail;
9059         if (exc)
9060                 goto fail;
9061
9062         num_named = read16 (named);
9063         named += 2;
9064         for (j = 0; j < num_named; j++) {
9065                 gint name_len;
9066                 char *name, named_type, data_type;
9067                 named_type = *named++;
9068                 data_type = *named++; /* type of data */
9069                 if (data_type == MONO_TYPE_SZARRAY)
9070                         data_type = *named++;
9071                 if (data_type == MONO_TYPE_ENUM) {
9072                         gint type_len;
9073                         char *type_name;
9074                         type_len = mono_metadata_decode_blob_size (named, &named);
9075                         type_name = (char *)g_malloc (type_len + 1);
9076                         memcpy (type_name, named, type_len);
9077                         type_name [type_len] = 0;
9078                         named += type_len;
9079                         /* FIXME: lookup the type and check type consistency */
9080                         g_free (type_name);
9081                 }
9082                 name_len = mono_metadata_decode_blob_size (named, &named);
9083                 name = (char *)g_malloc (name_len + 1);
9084                 memcpy (name, named, name_len);
9085                 name [name_len] = 0;
9086                 named += name_len;
9087                 if (named_type == 0x53) {
9088                         MonoClassField *field;
9089                         void *val;
9090
9091                         /* how this fail is a blackbox */
9092                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9093                         if (!field) {
9094                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9095                                 g_free (name);
9096                                 goto fail;
9097                         }
9098
9099                         val = load_cattr_value (image, field->type, named, &named, error);
9100                         if (!mono_error_ok (error)) {
9101                                 g_free (name);
9102                                 if (!type_is_reference (field->type))
9103                                         g_free (val);
9104                                 goto fail;
9105                         }
9106
9107                         mono_field_set_value (attr, field, val);
9108                         if (!type_is_reference (field->type))
9109                                 g_free (val);
9110                 } else if (named_type == 0x54) {
9111                         MonoProperty *prop;
9112                         void *pparams [1];
9113                         MonoType *prop_type;
9114
9115                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9116
9117                         if (!prop) {
9118                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9119                                 g_free (name);
9120                                 goto fail;
9121                         }
9122
9123                         if (!prop->set) {
9124                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9125                                 g_free (name);
9126                                 goto fail;
9127                         }
9128
9129                         /* can we have more that 1 arg in a custom attr named property? */
9130                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9131                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9132
9133                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9134                         if (!mono_error_ok (error)) {
9135                                 g_free (name);
9136                                 if (!type_is_reference (prop_type))
9137                                         g_free (pparams [0]);
9138                                 goto fail;
9139                         }
9140
9141
9142                         mono_property_set_value (prop, attr, pparams, NULL);
9143                         if (!type_is_reference (prop_type))
9144                                 g_free (pparams [0]);
9145                 }
9146                 g_free (name);
9147         }
9148
9149         free_param_data (method->signature, params);
9150         if (params != params_buf)
9151                 mono_gc_free_fixed (params);
9152
9153         return attr;
9154
9155 fail:
9156         free_param_data (method->signature, params);
9157         if (params != params_buf)
9158                 mono_gc_free_fixed (params);
9159         if (exc)
9160                 mono_raise_exception ((MonoException*)exc);
9161         return NULL;
9162 }
9163         
9164 /*
9165  * mono_reflection_create_custom_attr_data_args:
9166  *
9167  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9168  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9169  * NAMED_ARG_INFO will contain information about the named arguments.
9170  */
9171 void
9172 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)
9173 {
9174         MonoArray *typedargs, *namedargs;
9175         MonoClass *attrklass;
9176         MonoDomain *domain;
9177         const char *p = (const char*)data;
9178         const char *named;
9179         guint32 i, j, num_named;
9180         CattrNamedArg *arginfo = NULL;
9181
9182         *typed_args = NULL;
9183         *named_args = NULL;
9184         *named_arg_info = NULL;
9185
9186         mono_error_init (error);
9187
9188         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9189                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9190                 return;
9191         }
9192
9193         mono_class_init (method->klass);
9194         
9195         domain = mono_domain_get ();
9196
9197         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9198                 return;
9199
9200         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9201         
9202         /* skip prolog */
9203         p += 2;
9204         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9205                 MonoObject *obj;
9206                 void *val;
9207
9208                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9209                 if (!mono_error_ok (error)) {
9210                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9211                                 g_free (val);
9212                         return;
9213                 }
9214
9215                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9216                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9217                 mono_array_setref (typedargs, i, obj);
9218
9219                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9220                         g_free (val);
9221         }
9222
9223         named = p;
9224         num_named = read16 (named);
9225         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9226         named += 2;
9227         attrklass = method->klass;
9228
9229         arginfo = g_new0 (CattrNamedArg, num_named);
9230         *named_arg_info = arginfo;
9231
9232         for (j = 0; j < num_named; j++) {
9233                 gint name_len;
9234                 char *name, named_type, data_type;
9235                 named_type = *named++;
9236                 data_type = *named++; /* type of data */
9237                 if (data_type == MONO_TYPE_SZARRAY)
9238                         data_type = *named++;
9239                 if (data_type == MONO_TYPE_ENUM) {
9240                         gint type_len;
9241                         char *type_name;
9242                         type_len = mono_metadata_decode_blob_size (named, &named);
9243                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9244                                 goto fail;
9245
9246                         type_name = (char *)g_malloc (type_len + 1);
9247                         memcpy (type_name, named, type_len);
9248                         type_name [type_len] = 0;
9249                         named += type_len;
9250                         /* FIXME: lookup the type and check type consistency */
9251                         g_free (type_name);
9252                 }
9253                 name_len = mono_metadata_decode_blob_size (named, &named);
9254                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9255                         goto fail;
9256                 name = (char *)g_malloc (name_len + 1);
9257                 memcpy (name, named, name_len);
9258                 name [name_len] = 0;
9259                 named += name_len;
9260                 if (named_type == 0x53) {
9261                         MonoObject *obj;
9262                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9263                         void *val;
9264
9265                         if (!field) {
9266                                 g_free (name);
9267                                 goto fail;
9268                         }
9269
9270                         arginfo [j].type = field->type;
9271                         arginfo [j].field = field;
9272
9273                         val = load_cattr_value (image, field->type, named, &named, error);
9274                         if (!mono_error_ok (error)) {
9275                                 if (!type_is_reference (field->type))
9276                                         g_free (val);
9277                                 g_free (name);
9278                                 return;
9279                         }
9280
9281                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9282                         mono_array_setref (namedargs, j, obj);
9283                         if (!type_is_reference (field->type))
9284                                 g_free (val);
9285                 } else if (named_type == 0x54) {
9286                         MonoObject *obj;
9287                         MonoType *prop_type;
9288                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9289                         void *val;
9290
9291                         if (!prop || !prop->set) {
9292                                 g_free (name);
9293                                 goto fail;
9294                         }
9295
9296                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9297                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9298
9299                         arginfo [j].type = prop_type;
9300                         arginfo [j].prop = prop;
9301
9302                         val = load_cattr_value (image, prop_type, named, &named, error);
9303                         if (!mono_error_ok (error)) {
9304                                 if (!type_is_reference (prop_type))
9305                                         g_free (val);
9306                                 g_free (name);
9307                                 return;
9308                         }
9309
9310                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9311                         mono_array_setref (namedargs, j, obj);
9312                         if (!type_is_reference (prop_type))
9313                                 g_free (val);
9314                 }
9315                 g_free (name);
9316         }
9317
9318         *typed_args = typedargs;
9319         *named_args = namedargs;
9320         return;
9321 fail:
9322         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9323         g_free (arginfo);
9324         *named_arg_info = NULL;
9325 }
9326
9327 void
9328 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9329 {
9330         MonoDomain *domain;
9331         MonoArray *typedargs, *namedargs;
9332         MonoImage *image;
9333         MonoMethod *method;
9334         CattrNamedArg *arginfo = NULL;
9335         MonoError error;
9336         int i;
9337
9338         mono_error_init (&error);
9339
9340         *ctor_args = NULL;
9341         *named_args = NULL;
9342
9343         if (len == 0)
9344                 return;
9345
9346         image = assembly->assembly->image;
9347         method = ref_method->method;
9348         domain = mono_object_domain (ref_method);
9349
9350         if (!mono_class_init (method->klass))
9351                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9352
9353         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9354         if (!mono_error_ok (&error))
9355                 goto leave;
9356
9357         if (mono_loader_get_last_error ()) {
9358                 mono_error_set_from_loader_error (&error);
9359                 goto leave;
9360         }
9361
9362         if (!typedargs || !namedargs)
9363                 goto leave;
9364
9365         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9366                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9367                 MonoObject *typedarg;
9368
9369                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9370                 if (!is_ok (&error))
9371                         goto leave;
9372                 mono_array_setref (typedargs, i, typedarg);
9373         }
9374
9375         for (i = 0; i < mono_array_length (namedargs); ++i) {
9376                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9377                 MonoObject *typedarg, *namedarg, *minfo;
9378
9379                 if (arginfo [i].prop) {
9380                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9381                         if (!minfo)
9382                                 goto leave;
9383                 } else {
9384                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9385                         if (!mono_error_ok (&error))
9386                                 goto leave;
9387                 }
9388
9389                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9390                 if (!is_ok (&error))
9391                         goto leave;
9392                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9393                 if (!is_ok (&error))
9394                         goto leave;
9395
9396                 mono_array_setref (namedargs, i, namedarg);
9397         }
9398
9399         *ctor_args = typedargs;
9400         *named_args = namedargs;
9401 leave:
9402         g_free (arginfo);
9403         mono_error_raise_exception (&error);
9404
9405 }
9406
9407 static MonoObject*
9408 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9409 {
9410         static MonoMethod *ctor;
9411
9412         MonoDomain *domain;
9413         MonoObject *attr;
9414         void *params [4];
9415
9416         mono_error_init (error);
9417
9418         g_assert (image->assembly);
9419
9420         if (!ctor)
9421                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9422
9423         domain = mono_domain_get ();
9424         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9425         return_val_if_nok (error, NULL);
9426         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9427         return_val_if_nok (error, NULL);
9428         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9429         return_val_if_nok (error, NULL);
9430         params [2] = (gpointer)&cattr->data;
9431         params [3] = &cattr->data_size;
9432
9433         mono_runtime_invoke_checked (ctor, attr, params, error);
9434         return_val_if_nok (error, NULL);
9435         return attr;
9436 }
9437
9438 static MonoArray*
9439 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9440 {
9441         MonoArray *result;
9442         MonoObject *attr;
9443         int i, n;
9444
9445         mono_error_init (error);
9446
9447         n = 0;
9448         for (i = 0; i < cinfo->num_attrs; ++i) {
9449                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9450                         n ++;
9451         }
9452
9453         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9454         n = 0;
9455         for (i = 0; i < cinfo->num_attrs; ++i) {
9456                 if (!cinfo->attrs [i].ctor) {
9457                         /* The cattr type is not finished yet */
9458                         /* We should include the type name but cinfo doesn't contain it */
9459                         mono_error_set_type_load_name (error, NULL, NULL, "");
9460                         return NULL;
9461                 }
9462                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9463                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9464                         if (!mono_error_ok (error))
9465                                 return result;
9466                         mono_array_setref (result, n, attr);
9467                         n ++;
9468                 }
9469         }
9470         return result;
9471 }
9472
9473 MonoArray*
9474 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9475 {
9476         MonoError error;
9477         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9478         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9479
9480         return result;
9481 }
9482
9483 static MonoArray*
9484 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9485 {
9486         MonoArray *result;
9487         MonoObject *attr;
9488         int i;
9489         
9490         mono_error_init (error);
9491         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9492         for (i = 0; i < cinfo->num_attrs; ++i) {
9493                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9494                 return_val_if_nok (error, NULL);
9495                 mono_array_setref (result, i, attr);
9496         }
9497         return result;
9498 }
9499
9500 /**
9501  * mono_custom_attrs_from_index:
9502  *
9503  * Returns: NULL if no attributes are found or if a loading error occurs.
9504  */
9505 MonoCustomAttrInfo*
9506 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9507 {
9508         MonoError error;
9509         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9510         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9511         return result;
9512 }
9513 /**
9514  * mono_custom_attrs_from_index_checked:
9515  *
9516  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9517  */
9518 MonoCustomAttrInfo*
9519 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9520 {
9521         guint32 mtoken, i, len;
9522         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9523         MonoTableInfo *ca;
9524         MonoCustomAttrInfo *ainfo;
9525         GList *tmp, *list = NULL;
9526         const char *data;
9527         MonoCustomAttrEntry* attr;
9528
9529         mono_error_init (error);
9530
9531         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9532
9533         i = mono_metadata_custom_attrs_from_index (image, idx);
9534         if (!i)
9535                 return NULL;
9536         i --;
9537         while (i < ca->rows) {
9538                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9539                         break;
9540                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9541                 ++i;
9542         }
9543         len = g_list_length (list);
9544         if (!len)
9545                 return NULL;
9546         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9547         ainfo->num_attrs = len;
9548         ainfo->image = image;
9549         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9550                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9551                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9552                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9553                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9554                         mtoken |= MONO_TOKEN_METHOD_DEF;
9555                         break;
9556                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9557                         mtoken |= MONO_TOKEN_MEMBER_REF;
9558                         break;
9559                 default:
9560                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9561                         break;
9562                 }
9563                 attr = &ainfo->attrs [i - 1];
9564                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9565                 if (!attr->ctor) {
9566                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9567                         g_list_free (list);
9568                         g_free (ainfo);
9569                         return NULL;
9570                 }
9571
9572                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9573                         /*FIXME raising an exception here doesn't make any sense*/
9574                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9575                         g_list_free (list);
9576                         g_free (ainfo);
9577                         return NULL;
9578                 }
9579                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9580                 attr->data_size = mono_metadata_decode_value (data, &data);
9581                 attr->data = (guchar*)data;
9582         }
9583         g_list_free (list);
9584
9585         return ainfo;
9586 }
9587
9588 MonoCustomAttrInfo*
9589 mono_custom_attrs_from_method (MonoMethod *method)
9590 {
9591         MonoError error;
9592         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9593         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9594         return result;
9595 }
9596
9597 MonoCustomAttrInfo*
9598 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9599 {
9600         guint32 idx;
9601
9602         mono_error_init (error);
9603
9604         /*
9605          * An instantiated method has the same cattrs as the generic method definition.
9606          *
9607          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9608          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9609          */
9610         if (method->is_inflated)
9611                 method = ((MonoMethodInflated *) method)->declaring;
9612         
9613         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9614                 return lookup_custom_attr (method->klass->image, method);
9615
9616         if (!method->token)
9617                 /* Synthetic methods */
9618                 return NULL;
9619
9620         idx = mono_method_get_index (method);
9621         idx <<= MONO_CUSTOM_ATTR_BITS;
9622         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9623         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9624 }
9625
9626 MonoCustomAttrInfo*
9627 mono_custom_attrs_from_class (MonoClass *klass)
9628 {
9629         MonoError error;
9630         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9631         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9632         return result;
9633 }
9634
9635 MonoCustomAttrInfo*
9636 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9637 {
9638         guint32 idx;
9639
9640         mono_error_init (error);
9641
9642         if (klass->generic_class)
9643                 klass = klass->generic_class->container_class;
9644
9645         if (image_is_dynamic (klass->image))
9646                 return lookup_custom_attr (klass->image, klass);
9647
9648         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9649                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9650                 idx <<= MONO_CUSTOM_ATTR_BITS;
9651                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9652         } else {
9653                 idx = mono_metadata_token_index (klass->type_token);
9654                 idx <<= MONO_CUSTOM_ATTR_BITS;
9655                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9656         }
9657         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9658 }
9659
9660 MonoCustomAttrInfo*
9661 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9662 {
9663         MonoError error;
9664         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9665         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9666         return result;
9667 }
9668
9669 MonoCustomAttrInfo*
9670 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9671 {
9672         guint32 idx;
9673         
9674         mono_error_init (error);
9675
9676         if (image_is_dynamic (assembly->image))
9677                 return lookup_custom_attr (assembly->image, assembly);
9678         idx = 1; /* there is only one assembly */
9679         idx <<= MONO_CUSTOM_ATTR_BITS;
9680         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9681         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9682 }
9683
9684 static MonoCustomAttrInfo*
9685 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9686 {
9687         guint32 idx;
9688         
9689         if (image_is_dynamic (image))
9690                 return lookup_custom_attr (image, image);
9691         idx = 1; /* there is only one module */
9692         idx <<= MONO_CUSTOM_ATTR_BITS;
9693         idx |= MONO_CUSTOM_ATTR_MODULE;
9694         return mono_custom_attrs_from_index_checked (image, idx, error);
9695 }
9696
9697 MonoCustomAttrInfo*
9698 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9699 {
9700         MonoError error;
9701         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9702         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9703         return result;
9704 }
9705
9706 MonoCustomAttrInfo*
9707 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9708 {
9709         guint32 idx;
9710         
9711         if (image_is_dynamic (klass->image)) {
9712                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9713                 return lookup_custom_attr (klass->image, property);
9714         }
9715         idx = find_property_index (klass, property);
9716         idx <<= MONO_CUSTOM_ATTR_BITS;
9717         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9718         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9719 }
9720
9721 MonoCustomAttrInfo*
9722 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9723 {
9724         MonoError error;
9725         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9726         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9727         return result;
9728 }
9729
9730 MonoCustomAttrInfo*
9731 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9732 {
9733         guint32 idx;
9734         
9735         if (image_is_dynamic (klass->image)) {
9736                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9737                 return lookup_custom_attr (klass->image, event);
9738         }
9739         idx = find_event_index (klass, event);
9740         idx <<= MONO_CUSTOM_ATTR_BITS;
9741         idx |= MONO_CUSTOM_ATTR_EVENT;
9742         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9743 }
9744
9745 MonoCustomAttrInfo*
9746 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9747 {
9748         MonoError error;
9749         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9750         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9751         return result;
9752 }
9753
9754 MonoCustomAttrInfo*
9755 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9756 {
9757         guint32 idx;
9758         mono_error_init (error);
9759
9760         if (image_is_dynamic (klass->image)) {
9761                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9762                 return lookup_custom_attr (klass->image, field);
9763         }
9764         idx = find_field_index (klass, field);
9765         idx <<= MONO_CUSTOM_ATTR_BITS;
9766         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9767         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9768 }
9769
9770 /**
9771  * mono_custom_attrs_from_param:
9772  * @method: handle to the method that we want to retrieve custom parameter information from
9773  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9774  *
9775  * The result must be released with mono_custom_attrs_free().
9776  *
9777  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9778  */
9779 MonoCustomAttrInfo*
9780 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9781 {
9782         MonoError error;
9783         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9784         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9785         return result;
9786 }
9787
9788 /**
9789  * mono_custom_attrs_from_param_checked:
9790  * @method: handle to the method that we want to retrieve custom parameter information from
9791  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9792  * @error: set on error
9793  *
9794  * The result must be released with mono_custom_attrs_free().
9795  *
9796  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9797  */
9798 MonoCustomAttrInfo*
9799 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9800 {
9801         MonoTableInfo *ca;
9802         guint32 i, idx, method_index;
9803         guint32 param_list, param_last, param_pos, found;
9804         MonoImage *image;
9805         MonoReflectionMethodAux *aux;
9806
9807         mono_error_init (error);
9808
9809         /*
9810          * An instantiated method has the same cattrs as the generic method definition.
9811          *
9812          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9813          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9814          */
9815         if (method->is_inflated)
9816                 method = ((MonoMethodInflated *) method)->declaring;
9817
9818         if (image_is_dynamic (method->klass->image)) {
9819                 MonoCustomAttrInfo *res, *ainfo;
9820                 int size;
9821
9822                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9823                 if (!aux || !aux->param_cattr)
9824                         return NULL;
9825
9826                 /* Need to copy since it will be freed later */
9827                 ainfo = aux->param_cattr [param];
9828                 if (!ainfo)
9829                         return NULL;
9830                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9831                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9832                 memcpy (res, ainfo, size);
9833                 return res;
9834         }
9835
9836         image = method->klass->image;
9837         method_index = mono_method_get_index (method);
9838         if (!method_index)
9839                 return NULL;
9840         ca = &image->tables [MONO_TABLE_METHOD];
9841
9842         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9843         if (method_index == ca->rows) {
9844                 ca = &image->tables [MONO_TABLE_PARAM];
9845                 param_last = ca->rows + 1;
9846         } else {
9847                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9848                 ca = &image->tables [MONO_TABLE_PARAM];
9849         }
9850         found = FALSE;
9851         for (i = param_list; i < param_last; ++i) {
9852                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9853                 if (param_pos == param) {
9854                         found = TRUE;
9855                         break;
9856                 }
9857         }
9858         if (!found)
9859                 return NULL;
9860         idx = i;
9861         idx <<= MONO_CUSTOM_ATTR_BITS;
9862         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9863         return mono_custom_attrs_from_index_checked (image, idx, error);
9864 }
9865
9866 gboolean
9867 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9868 {
9869         int i;
9870         MonoClass *klass;
9871         for (i = 0; i < ainfo->num_attrs; ++i) {
9872                 klass = ainfo->attrs [i].ctor->klass;
9873                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9874                         return TRUE;
9875         }
9876         return FALSE;
9877 }
9878
9879 MonoObject*
9880 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9881 {
9882         MonoError error;
9883         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9884         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9885         return res;
9886 }
9887
9888 MonoObject*
9889 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9890 {
9891         int i, attr_index;
9892         MonoClass *klass;
9893         MonoArray *attrs;
9894
9895         mono_error_init (error);
9896
9897         attr_index = -1;
9898         for (i = 0; i < ainfo->num_attrs; ++i) {
9899                 klass = ainfo->attrs [i].ctor->klass;
9900                 if (mono_class_has_parent (klass, attr_klass)) {
9901                         attr_index = i;
9902                         break;
9903                 }
9904         }
9905         if (attr_index == -1)
9906                 return NULL;
9907
9908         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9909         if (!mono_error_ok (error))
9910                 return NULL;
9911         return mono_array_get (attrs, MonoObject*, attr_index);
9912 }
9913
9914 /*
9915  * mono_reflection_get_custom_attrs_info:
9916  * @obj: a reflection object handle
9917  *
9918  * Return the custom attribute info for attributes defined for the
9919  * reflection handle @obj. The objects.
9920  *
9921  * FIXME this function leaks like a sieve for SRE objects.
9922  */
9923 MonoCustomAttrInfo*
9924 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9925 {
9926         MonoError error;
9927         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9928         mono_error_assert_ok (&error);
9929         return result;
9930 }
9931
9932 /**
9933  * mono_reflection_get_custom_attrs_info_checked:
9934  * @obj: a reflection object handle
9935  * @error: set on error
9936  *
9937  * Return the custom attribute info for attributes defined for the
9938  * reflection handle @obj. The objects.
9939  *
9940  * On failure returns NULL and sets @error.
9941  *
9942  * FIXME this function leaks like a sieve for SRE objects.
9943  */
9944 MonoCustomAttrInfo*
9945 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9946 {
9947         MonoClass *klass;
9948         MonoCustomAttrInfo *cinfo = NULL;
9949         
9950         mono_error_init (error);
9951
9952         klass = obj->vtable->klass;
9953         if (klass == mono_defaults.monotype_class) {
9954                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9955                 klass = mono_class_from_mono_type (type);
9956                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9957                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
9958                 return_val_if_nok (error, NULL);
9959         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9960                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9961                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
9962                 return_val_if_nok (error, NULL);
9963         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9964                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9965                 cinfo = mono_custom_attrs_from_module (module->image, error);
9966                 return_val_if_nok (error, NULL);
9967         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9968                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9969                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
9970                 return_val_if_nok (error, NULL);
9971         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9972                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9973                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
9974                 return_val_if_nok (error, NULL);
9975         } else if (strcmp ("MonoField", klass->name) == 0) {
9976                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9977                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
9978                 return_val_if_nok (error, NULL);
9979         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9980                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9981                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9982                 return_val_if_nok (error, NULL);
9983         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9984                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9985                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
9986                 return_val_if_nok (error, NULL);
9987         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9988                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9989                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9990                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9991                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9992                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
9993                         return_val_if_nok (error, NULL);
9994                 } else if (is_sr_mono_property (member_class)) {
9995                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9996                         MonoMethod *method;
9997                         if (!(method = prop->property->get))
9998                                 method = prop->property->set;
9999                         g_assert (method);
10000
10001                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10002                         return_val_if_nok (error, NULL);
10003                 } 
10004 #ifndef DISABLE_REFLECTION_EMIT
10005                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10006                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10007                         return_val_if_nok (error, NULL);
10008                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10009                         return_val_if_nok (error, NULL);
10010                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10011                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10012                         MonoMethod *method = NULL;
10013                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10014                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10015                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10016                                 method = ((MonoReflectionMethod *)c->cb)->method;
10017                         else
10018                                 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));
10019
10020                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10021                         return_val_if_nok (error, NULL);
10022                 } 
10023 #endif
10024                 else {
10025                         char *type_name = mono_type_get_full_name (member_class);
10026                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10027                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10028                                                       type_name);
10029                         g_free (type_name);
10030                         return NULL;
10031                 }
10032         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10033                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10034                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10035         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10036                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10037                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10038         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10039                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10040                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10041         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10042                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10043                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10044         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10045                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10046                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10047         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10048                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10049                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10050         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10051                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10052                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10053                 return_val_if_nok (error, NULL);
10054         } else { /* handle other types here... */
10055                 g_error ("get custom attrs not yet supported for %s", klass->name);
10056         }
10057
10058         return cinfo;
10059 }
10060
10061 /*
10062  * mono_reflection_get_custom_attrs_by_type:
10063  * @obj: a reflection object handle
10064  *
10065  * Return an array with all the custom attributes defined of the
10066  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10067  * of that type are returned. The objects are fully build. Return NULL if a loading error
10068  * occurs.
10069  */
10070 MonoArray*
10071 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10072 {
10073         MonoArray *result;
10074         MonoCustomAttrInfo *cinfo;
10075
10076         mono_error_init (error);
10077
10078         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10079         return_val_if_nok (error, NULL);
10080         if (cinfo) {
10081                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10082                 if (!result)
10083                         return NULL;
10084                 if (!cinfo->cached)
10085                         mono_custom_attrs_free (cinfo);
10086         } else {
10087                 mono_loader_assert_no_error ();
10088                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10089         }
10090
10091         return result;
10092 }
10093
10094 /*
10095  * mono_reflection_get_custom_attrs:
10096  * @obj: a reflection object handle
10097  *
10098  * Return an array with all the custom attributes defined of the
10099  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10100  * occurs.
10101  */
10102 MonoArray*
10103 mono_reflection_get_custom_attrs (MonoObject *obj)
10104 {
10105         MonoError error;
10106
10107         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10108 }
10109
10110 /*
10111  * mono_reflection_get_custom_attrs_data:
10112  * @obj: a reflection obj handle
10113  *
10114  * Returns an array of System.Reflection.CustomAttributeData,
10115  * which include information about attributes reflected on
10116  * types loaded using the Reflection Only methods
10117  */
10118 MonoArray*
10119 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10120 {
10121         MonoError error;
10122         MonoArray* result;
10123         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10124         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10125         return result;
10126 }
10127
10128 /*
10129  * mono_reflection_get_custom_attrs_data_checked:
10130  * @obj: a reflection obj handle
10131  * @error: set on error
10132  *
10133  * Returns an array of System.Reflection.CustomAttributeData,
10134  * which include information about attributes reflected on
10135  * types loaded using the Reflection Only methods
10136  */
10137 MonoArray*
10138 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10139 {
10140         MonoArray *result;
10141         MonoCustomAttrInfo *cinfo;
10142
10143         mono_error_init (error);
10144
10145         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10146         return_val_if_nok (error, NULL);
10147         if (cinfo) {
10148                 result = mono_custom_attrs_data_construct (cinfo, error);
10149                 return_val_if_nok (error, NULL);
10150                 if (!cinfo->cached)
10151                         mono_custom_attrs_free (cinfo);
10152         } else
10153                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10154
10155         if (mono_loader_get_last_error ())
10156                 mono_error_set_from_loader_error (error);
10157
10158         return result;
10159 }
10160
10161 static MonoReflectionType*
10162 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10163 {
10164         static MonoMethod *method_get_underlying_system_type = NULL;
10165         MonoReflectionType *rt;
10166         MonoMethod *usertype_method;
10167
10168         mono_error_init (error);
10169
10170         if (!method_get_underlying_system_type)
10171                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10172
10173         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10174
10175         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10176
10177         return rt;
10178 }
10179
10180
10181 static gboolean
10182 is_corlib_type (MonoClass *klass)
10183 {
10184         return klass->image == mono_defaults.corlib;
10185 }
10186
10187 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10188         static MonoClass *cached_class; \
10189         if (cached_class) \
10190                 return cached_class == _class; \
10191         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10192                 cached_class = _class; \
10193                 return TRUE; \
10194         } \
10195         return FALSE; \
10196 } while (0) \
10197
10198
10199 #ifndef DISABLE_REFLECTION_EMIT
10200 static gboolean
10201 is_sre_array (MonoClass *klass)
10202 {
10203         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10204 }
10205
10206 static gboolean
10207 is_sre_byref (MonoClass *klass)
10208 {
10209         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10210 }
10211
10212 static gboolean
10213 is_sre_pointer (MonoClass *klass)
10214 {
10215         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10216 }
10217
10218 static gboolean
10219 is_sre_generic_instance (MonoClass *klass)
10220 {
10221         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10222 }
10223
10224 static gboolean
10225 is_sre_type_builder (MonoClass *klass)
10226 {
10227         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10228 }
10229
10230 static gboolean
10231 is_sre_method_builder (MonoClass *klass)
10232 {
10233         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10234 }
10235
10236 static gboolean
10237 is_sre_ctor_builder (MonoClass *klass)
10238 {
10239         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10240 }
10241
10242 static gboolean
10243 is_sre_field_builder (MonoClass *klass)
10244 {
10245         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10246 }
10247
10248 static gboolean
10249 is_sre_method_on_tb_inst (MonoClass *klass)
10250 {
10251         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10252 }
10253
10254 static gboolean
10255 is_sre_ctor_on_tb_inst (MonoClass *klass)
10256 {
10257         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10258 }
10259
10260 MonoType*
10261 mono_reflection_type_get_handle (MonoReflectionType* ref)
10262 {
10263         MonoError error;
10264         MonoClass *klass;
10265         if (!ref)
10266                 return NULL;
10267         if (ref->type)
10268                 return ref->type;
10269
10270         if (is_usertype (ref)) {
10271                 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10272                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10273                 if (ref == NULL || is_usertype (ref))
10274                         return NULL;
10275                 if (ref->type)
10276                         return ref->type;
10277         }
10278
10279         klass = mono_object_class (ref);
10280
10281         if (is_sre_array (klass)) {
10282                 MonoType *res;
10283                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10284                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10285                 g_assert (base);
10286                 if (sre_array->rank == 0) //single dimentional array
10287                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10288                 else
10289                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10290                 sre_array->type.type = res;
10291                 return res;
10292         } else if (is_sre_byref (klass)) {
10293                 MonoType *res;
10294                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10295                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10296                 g_assert (base);
10297                 res = &mono_class_from_mono_type (base)->this_arg;
10298                 sre_byref->type.type = res;
10299                 return res;
10300         } else if (is_sre_pointer (klass)) {
10301                 MonoType *res;
10302                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10303                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10304                 g_assert (base);
10305                 res = &mono_ptr_class_get (base)->byval_arg;
10306                 sre_pointer->type.type = res;
10307                 return res;
10308         } else if (is_sre_generic_instance (klass)) {
10309                 MonoType *res, **types;
10310                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10311                 int i, count;
10312
10313                 count = mono_array_length (gclass->type_arguments);
10314                 types = g_new0 (MonoType*, count);
10315                 for (i = 0; i < count; ++i) {
10316                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10317                         types [i] = mono_reflection_type_get_handle (t);
10318                         if (!types[i]) {
10319                                 g_free (types);
10320                                 return NULL;
10321                         }
10322                 }
10323
10324                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10325                 g_free (types);
10326                 g_assert (res);
10327                 gclass->type.type = res;
10328                 return res;
10329         }
10330
10331         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10332         return NULL;
10333 }
10334
10335
10336
10337 void
10338 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10339 {
10340         mono_reflection_type_get_handle (type);
10341 }
10342
10343 void
10344 mono_reflection_register_with_runtime (MonoReflectionType *type)
10345 {
10346         MonoType *res = mono_reflection_type_get_handle (type);
10347         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10348         MonoClass *klass;
10349
10350         if (!res)
10351                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10352
10353         klass = mono_class_from_mono_type (res);
10354
10355         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10356         mono_domain_lock (domain);
10357
10358         if (!image_is_dynamic (klass->image)) {
10359                 mono_class_setup_supertypes (klass);
10360         } else {
10361                 if (!domain->type_hash)
10362                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10363                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10364                 mono_g_hash_table_insert (domain->type_hash, res, type);
10365         }
10366         mono_domain_unlock (domain);
10367         mono_loader_unlock ();
10368 }
10369
10370 /**
10371  * LOCKING: Assumes the loader lock is held.
10372  */
10373 static MonoMethodSignature*
10374 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10375         MonoMethodSignature *sig;
10376         int count, i;
10377
10378         count = parameters? mono_array_length (parameters): 0;
10379
10380         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10381         sig->param_count = count;
10382         sig->sentinelpos = -1; /* FIXME */
10383         for (i = 0; i < count; ++i)
10384                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10385         return sig;
10386 }
10387
10388 /**
10389  * LOCKING: Assumes the loader lock is held.
10390  */
10391 static MonoMethodSignature*
10392 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10393         MonoMethodSignature *sig;
10394
10395         sig = parameters_to_signature (image, ctor->parameters);
10396         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10397         sig->ret = &mono_defaults.void_class->byval_arg;
10398         return sig;
10399 }
10400
10401 /**
10402  * LOCKING: Assumes the loader lock is held.
10403  */
10404 static MonoMethodSignature*
10405 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10406         MonoMethodSignature *sig;
10407
10408         sig = parameters_to_signature (image, method->parameters);
10409         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10410         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10411         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10412         return sig;
10413 }
10414
10415 static MonoMethodSignature*
10416 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10417         MonoMethodSignature *sig;
10418
10419         sig = parameters_to_signature (NULL, method->parameters);
10420         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10421         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10422         sig->generic_param_count = 0;
10423         return sig;
10424 }
10425
10426 static void
10427 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10428 {
10429         MonoClass *klass = mono_object_class (prop);
10430         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10431                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10432                 *name = mono_string_to_utf8 (pb->name);
10433                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10434         } else {
10435                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10436                 *name = g_strdup (p->property->name);
10437                 if (p->property->get)
10438                         *type = mono_method_signature (p->property->get)->ret;
10439                 else
10440                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10441         }
10442 }
10443
10444 static void
10445 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10446 {
10447         MonoClass *klass = mono_object_class (field);
10448         if (strcmp (klass->name, "FieldBuilder") == 0) {
10449                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10450                 *name = mono_string_to_utf8 (fb->name);
10451                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10452         } else {
10453                 MonoReflectionField *f = (MonoReflectionField *)field;
10454                 *name = g_strdup (mono_field_get_name (f->field));
10455                 *type = f->field->type;
10456         }
10457 }
10458
10459 #else /* DISABLE_REFLECTION_EMIT */
10460
10461 void
10462 mono_reflection_register_with_runtime (MonoReflectionType *type)
10463 {
10464         /* This is empty */
10465 }
10466
10467 static gboolean
10468 is_sre_type_builder (MonoClass *klass)
10469 {
10470         return FALSE;
10471 }
10472
10473 static gboolean
10474 is_sre_generic_instance (MonoClass *klass)
10475 {
10476         return FALSE;
10477 }
10478
10479 static void
10480 init_type_builder_generics (MonoObject *type)
10481 {
10482 }
10483
10484 #endif /* !DISABLE_REFLECTION_EMIT */
10485
10486
10487 static gboolean
10488 is_sr_mono_field (MonoClass *klass)
10489 {
10490         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10491 }
10492
10493 static gboolean
10494 is_sr_mono_property (MonoClass *klass)
10495 {
10496         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10497 }
10498
10499 static gboolean
10500 is_sr_mono_method (MonoClass *klass)
10501 {
10502         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10503 }
10504
10505 static gboolean
10506 is_sr_mono_cmethod (MonoClass *klass)
10507 {
10508         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10509 }
10510
10511 static gboolean
10512 is_sr_mono_generic_method (MonoClass *klass)
10513 {
10514         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10515 }
10516
10517 static gboolean
10518 is_sr_mono_generic_cmethod (MonoClass *klass)
10519 {
10520         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10521 }
10522
10523 gboolean
10524 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10525 {
10526         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10527 }
10528
10529 static gboolean
10530 is_usertype (MonoReflectionType *ref)
10531 {
10532         MonoClass *klass = mono_object_class (ref);
10533         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10534 }
10535
10536 static MonoReflectionType*
10537 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10538 {
10539         mono_error_init (error);
10540         if (!type || type->type)
10541                 return type;
10542
10543         if (is_usertype (type)) {
10544                 type = mono_reflection_type_get_underlying_system_type (type, error);
10545                 return_val_if_nok (error, NULL);
10546                 if (is_usertype (type)) {
10547                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10548                         return NULL;
10549                 }
10550         }
10551
10552         return type;
10553 }
10554 /*
10555  * Encode a value in a custom attribute stream of bytes.
10556  * The value to encode is either supplied as an object in argument val
10557  * (valuetypes are boxed), or as a pointer to the data in the
10558  * argument argval.
10559  * @type represents the type of the value
10560  * @buffer is the start of the buffer
10561  * @p the current position in the buffer
10562  * @buflen contains the size of the buffer and is used to return the new buffer size
10563  * if this needs to be realloced.
10564  * @retbuffer and @retp return the start and the position of the buffer
10565  */
10566 static void
10567 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10568 {
10569         MonoTypeEnum simple_type;
10570         
10571         if ((p-buffer) + 10 >= *buflen) {
10572                 char *newbuf;
10573                 *buflen *= 2;
10574                 newbuf = (char *)g_realloc (buffer, *buflen);
10575                 p = newbuf + (p-buffer);
10576                 buffer = newbuf;
10577         }
10578         if (!argval)
10579                 argval = ((char*)arg + sizeof (MonoObject));
10580         simple_type = type->type;
10581 handle_enum:
10582         switch (simple_type) {
10583         case MONO_TYPE_BOOLEAN:
10584         case MONO_TYPE_U1:
10585         case MONO_TYPE_I1:
10586                 *p++ = *argval;
10587                 break;
10588         case MONO_TYPE_CHAR:
10589         case MONO_TYPE_U2:
10590         case MONO_TYPE_I2:
10591                 swap_with_size (p, argval, 2, 1);
10592                 p += 2;
10593                 break;
10594         case MONO_TYPE_U4:
10595         case MONO_TYPE_I4:
10596         case MONO_TYPE_R4:
10597                 swap_with_size (p, argval, 4, 1);
10598                 p += 4;
10599                 break;
10600         case MONO_TYPE_R8:
10601                 swap_with_size (p, argval, 8, 1);
10602                 p += 8;
10603                 break;
10604         case MONO_TYPE_U8:
10605         case MONO_TYPE_I8:
10606                 swap_with_size (p, argval, 8, 1);
10607                 p += 8;
10608                 break;
10609         case MONO_TYPE_VALUETYPE:
10610                 if (type->data.klass->enumtype) {
10611                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10612                         goto handle_enum;
10613                 } else {
10614                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10615                 }
10616                 break;
10617         case MONO_TYPE_STRING: {
10618                 char *str;
10619                 guint32 slen;
10620                 if (!arg) {
10621                         *p++ = 0xFF;
10622                         break;
10623                 }
10624                 str = mono_string_to_utf8 ((MonoString*)arg);
10625                 slen = strlen (str);
10626                 if ((p-buffer) + 10 + slen >= *buflen) {
10627                         char *newbuf;
10628                         *buflen *= 2;
10629                         *buflen += slen;
10630                         newbuf = (char *)g_realloc (buffer, *buflen);
10631                         p = newbuf + (p-buffer);
10632                         buffer = newbuf;
10633                 }
10634                 mono_metadata_encode_value (slen, p, &p);
10635                 memcpy (p, str, slen);
10636                 p += slen;
10637                 g_free (str);
10638                 break;
10639         }
10640         case MONO_TYPE_CLASS: {
10641                 char *str;
10642                 guint32 slen;
10643                 if (!arg) {
10644                         *p++ = 0xFF;
10645                         break;
10646                 }
10647 handle_type:
10648                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10649                 slen = strlen (str);
10650                 if ((p-buffer) + 10 + slen >= *buflen) {
10651                         char *newbuf;
10652                         *buflen *= 2;
10653                         *buflen += slen;
10654                         newbuf = (char *)g_realloc (buffer, *buflen);
10655                         p = newbuf + (p-buffer);
10656                         buffer = newbuf;
10657                 }
10658                 mono_metadata_encode_value (slen, p, &p);
10659                 memcpy (p, str, slen);
10660                 p += slen;
10661                 g_free (str);
10662                 break;
10663         }
10664         case MONO_TYPE_SZARRAY: {
10665                 int len, i;
10666                 MonoClass *eclass, *arg_eclass;
10667
10668                 if (!arg) {
10669                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10670                         break;
10671                 }
10672                 len = mono_array_length ((MonoArray*)arg);
10673                 *p++ = len & 0xff;
10674                 *p++ = (len >> 8) & 0xff;
10675                 *p++ = (len >> 16) & 0xff;
10676                 *p++ = (len >> 24) & 0xff;
10677                 *retp = p;
10678                 *retbuffer = buffer;
10679                 eclass = type->data.klass;
10680                 arg_eclass = mono_object_class (arg)->element_class;
10681
10682                 if (!eclass) {
10683                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10684                         eclass = mono_defaults.object_class;
10685                 }
10686                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10687                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10688                         int elsize = mono_class_array_element_size (arg_eclass);
10689                         for (i = 0; i < len; ++i) {
10690                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10691                                 elptr += elsize;
10692                         }
10693                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10694                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10695                         int elsize = mono_class_array_element_size (eclass);
10696                         for (i = 0; i < len; ++i) {
10697                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10698                                 elptr += elsize;
10699                         }
10700                 } else {
10701                         for (i = 0; i < len; ++i) {
10702                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10703                         }
10704                 }
10705                 break;
10706         }
10707         case MONO_TYPE_OBJECT: {
10708                 MonoClass *klass;
10709                 char *str;
10710                 guint32 slen;
10711
10712                 /*
10713                  * The parameter type is 'object' but the type of the actual
10714                  * argument is not. So we have to add type information to the blob
10715                  * too. This is completely undocumented in the spec.
10716                  */
10717
10718                 if (arg == NULL) {
10719                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10720                         *p++ = 0xFF;
10721                         break;
10722                 }
10723                 
10724                 klass = mono_object_class (arg);
10725
10726                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10727                         *p++ = 0x50;
10728                         goto handle_type;
10729                 } else if (klass->enumtype) {
10730                         *p++ = 0x55;
10731                 } else if (klass == mono_defaults.string_class) {
10732                         simple_type = MONO_TYPE_STRING;
10733                         *p++ = 0x0E;
10734                         goto handle_enum;
10735                 } else if (klass->rank == 1) {
10736                         *p++ = 0x1D;
10737                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10738                                 /* See Partition II, Appendix B3 */
10739                                 *p++ = 0x51;
10740                         else
10741                                 *p++ = klass->element_class->byval_arg.type;
10742                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10743                         break;
10744                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10745                         *p++ = simple_type = klass->byval_arg.type;
10746                         goto handle_enum;
10747                 } else {
10748                         g_error ("unhandled type in custom attr");
10749                 }
10750                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10751                 slen = strlen (str);
10752                 if ((p-buffer) + 10 + slen >= *buflen) {
10753                         char *newbuf;
10754                         *buflen *= 2;
10755                         *buflen += slen;
10756                         newbuf = (char *)g_realloc (buffer, *buflen);
10757                         p = newbuf + (p-buffer);
10758                         buffer = newbuf;
10759                 }
10760                 mono_metadata_encode_value (slen, p, &p);
10761                 memcpy (p, str, slen);
10762                 p += slen;
10763                 g_free (str);
10764                 simple_type = mono_class_enum_basetype (klass)->type;
10765                 goto handle_enum;
10766         }
10767         default:
10768                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10769         }
10770         *retp = p;
10771         *retbuffer = buffer;
10772 }
10773
10774 static void
10775 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10776 {
10777         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10778                 char *str = type_get_qualified_name (type, NULL);
10779                 int slen = strlen (str);
10780
10781                 *p++ = 0x55;
10782                 /*
10783                  * This seems to be optional...
10784                  * *p++ = 0x80;
10785                  */
10786                 mono_metadata_encode_value (slen, p, &p);
10787                 memcpy (p, str, slen);
10788                 p += slen;
10789                 g_free (str);
10790         } else if (type->type == MONO_TYPE_OBJECT) {
10791                 *p++ = 0x51;
10792         } else if (type->type == MONO_TYPE_CLASS) {
10793                 /* it should be a type: encode_cattr_value () has the check */
10794                 *p++ = 0x50;
10795         } else {
10796                 mono_metadata_encode_value (type->type, p, &p);
10797                 if (type->type == MONO_TYPE_SZARRAY)
10798                         /* See the examples in Partition VI, Annex B */
10799                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10800         }
10801
10802         *retp = p;
10803 }
10804
10805 #ifndef DISABLE_REFLECTION_EMIT
10806 static void
10807 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10808 {
10809         int len;
10810         /* Preallocate a large enough buffer */
10811         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10812                 char *str = type_get_qualified_name (type, NULL);
10813                 len = strlen (str);
10814                 g_free (str);
10815         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10816                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10817                 len = strlen (str);
10818                 g_free (str);
10819         } else {
10820                 len = 0;
10821         }
10822         len += strlen (name);
10823
10824         if ((p-buffer) + 20 + len >= *buflen) {
10825                 char *newbuf;
10826                 *buflen *= 2;
10827                 *buflen += len;
10828                 newbuf = (char *)g_realloc (buffer, *buflen);
10829                 p = newbuf + (p-buffer);
10830                 buffer = newbuf;
10831         }
10832
10833         encode_field_or_prop_type (type, p, &p);
10834
10835         len = strlen (name);
10836         mono_metadata_encode_value (len, p, &p);
10837         memcpy (p, name, len);
10838         p += len;
10839         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10840         *retp = p;
10841         *retbuffer = buffer;
10842 }
10843
10844 /*
10845  * mono_reflection_get_custom_attrs_blob:
10846  * @ctor: custom attribute constructor
10847  * @ctorArgs: arguments o the constructor
10848  * @properties:
10849  * @propValues:
10850  * @fields:
10851  * @fieldValues:
10852  * 
10853  * Creates the blob of data that needs to be saved in the metadata and that represents
10854  * the custom attributed described by @ctor, @ctorArgs etc.
10855  * Returns: a Byte array representing the blob of data.
10856  */
10857 MonoArray*
10858 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10859 {
10860         MonoArray *result;
10861         MonoMethodSignature *sig;
10862         MonoObject *arg;
10863         char *buffer, *p;
10864         guint32 buflen, i;
10865
10866         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10867                 /* sig is freed later so allocate it in the heap */
10868                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10869         } else {
10870                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10871         }
10872
10873         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10874         buflen = 256;
10875         p = buffer = (char *)g_malloc (buflen);
10876         /* write the prolog */
10877         *p++ = 1;
10878         *p++ = 0;
10879         for (i = 0; i < sig->param_count; ++i) {
10880                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10881                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10882         }
10883         i = 0;
10884         if (properties)
10885                 i += mono_array_length (properties);
10886         if (fields)
10887                 i += mono_array_length (fields);
10888         *p++ = i & 0xff;
10889         *p++ = (i >> 8) & 0xff;
10890         if (properties) {
10891                 MonoObject *prop;
10892                 for (i = 0; i < mono_array_length (properties); ++i) {
10893                         MonoType *ptype;
10894                         char *pname;
10895
10896                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10897                         get_prop_name_and_type (prop, &pname, &ptype);
10898                         *p++ = 0x54; /* PROPERTY signature */
10899                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10900                         g_free (pname);
10901                 }
10902         }
10903
10904         if (fields) {
10905                 MonoObject *field;
10906                 for (i = 0; i < mono_array_length (fields); ++i) {
10907                         MonoType *ftype;
10908                         char *fname;
10909
10910                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10911                         get_field_name_and_type (field, &fname, &ftype);
10912                         *p++ = 0x53; /* FIELD signature */
10913                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10914                         g_free (fname);
10915                 }
10916         }
10917
10918         g_assert (p - buffer <= buflen);
10919         buflen = p - buffer;
10920         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10921         p = mono_array_addr (result, char, 0);
10922         memcpy (p, buffer, buflen);
10923         g_free (buffer);
10924         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10925                 g_free (sig);
10926         return result;
10927 }
10928
10929 /*
10930  * mono_reflection_setup_internal_class:
10931  * @tb: a TypeBuilder object
10932  *
10933  * Creates a MonoClass that represents the TypeBuilder.
10934  * This is a trick that lets us simplify a lot of reflection code
10935  * (and will allow us to support Build and Run assemblies easier).
10936  */
10937 void
10938 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10939 {
10940         MonoError error;
10941         MonoClass *klass, *parent;
10942
10943         RESOLVE_TYPE (tb->parent, &error);
10944         mono_error_raise_exception (&error); /* FIXME don't raise here */
10945
10946         mono_loader_lock ();
10947
10948         if (tb->parent) {
10949                 /* check so we can compile corlib correctly */
10950                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10951                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10952                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10953                 } else {
10954                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10955                 }
10956         } else {
10957                 parent = NULL;
10958         }
10959         
10960         /* the type has already being created: it means we just have to change the parent */
10961         if (tb->type.type) {
10962                 klass = mono_class_from_mono_type (tb->type.type);
10963                 klass->parent = NULL;
10964                 /* fool mono_class_setup_parent */
10965                 klass->supertypes = NULL;
10966                 mono_class_setup_parent (klass, parent);
10967                 mono_class_setup_mono_type (klass);
10968                 mono_loader_unlock ();
10969                 return;
10970         }
10971
10972         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10973
10974         klass->image = &tb->module->dynamic_image->image;
10975
10976         klass->inited = 1; /* we lie to the runtime */
10977         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10978         if (!mono_error_ok (&error))
10979                 goto failure;
10980         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10981         if (!mono_error_ok (&error))
10982                 goto failure;
10983         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10984         klass->flags = tb->attrs;
10985         
10986         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10987
10988         klass->element_class = klass;
10989
10990         if (mono_class_get_ref_info (klass) == NULL) {
10991
10992                 mono_class_set_ref_info (klass, tb);
10993
10994                 /* Put into cache so mono_class_get_checked () will find it.
10995                 Skip nested types as those should not be available on the global scope. */
10996                 if (!tb->nesting_type)
10997                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10998
10999                 /*
11000                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11001                 by performing a mono_class_get which does the full resolution.
11002
11003                 Working around this semantics would require us to write a lot of code for no clear advantage.
11004                 */
11005                 mono_image_append_class_to_reflection_info_set (klass);
11006         } else {
11007                 g_assert (mono_class_get_ref_info (klass) == tb);
11008         }
11009
11010         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11011
11012         if (parent != NULL) {
11013                 mono_class_setup_parent (klass, parent);
11014         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11015                 const char *old_n = klass->name;
11016                 /* trick to get relative numbering right when compiling corlib */
11017                 klass->name = "BuildingObject";
11018                 mono_class_setup_parent (klass, mono_defaults.object_class);
11019                 klass->name = old_n;
11020         }
11021
11022         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11023                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11024                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11025                 klass->instance_size = sizeof (MonoObject);
11026                 klass->size_inited = 1;
11027                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11028         }
11029
11030         mono_class_setup_mono_type (klass);
11031
11032         mono_class_setup_supertypes (klass);
11033
11034         /*
11035          * FIXME: handle interfaces.
11036          */
11037
11038         tb->type.type = &klass->byval_arg;
11039
11040         if (tb->nesting_type) {
11041                 g_assert (tb->nesting_type->type);
11042                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
11043         }
11044
11045         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11046
11047         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11048         
11049         mono_loader_unlock ();
11050         return;
11051
11052 failure:
11053         mono_loader_unlock ();
11054         mono_error_raise_exception (&error);
11055 }
11056
11057 /*
11058  * mono_reflection_setup_generic_class:
11059  * @tb: a TypeBuilder object
11060  *
11061  * Setup the generic class before adding the first generic parameter.
11062  */
11063 void
11064 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11065 {
11066 }
11067
11068 /*
11069  * mono_reflection_create_generic_class:
11070  * @tb: a TypeBuilder object
11071  *
11072  * Creates the generic class after all generic parameters have been added.
11073  */
11074 void
11075 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11076 {
11077         MonoClass *klass;
11078         int count, i;
11079
11080         klass = mono_class_from_mono_type (tb->type.type);
11081
11082         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11083
11084         if (klass->generic_container || (count == 0))
11085                 return;
11086
11087         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11088
11089         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11090
11091         klass->generic_container->owner.klass = klass;
11092         klass->generic_container->type_argc = count;
11093         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11094
11095         klass->is_generic = 1;
11096
11097         for (i = 0; i < count; i++) {
11098                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11099                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
11100                 klass->generic_container->type_params [i] = *param;
11101                 /*Make sure we are a diferent type instance */
11102                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11103                 klass->generic_container->type_params [i].info.pklass = NULL;
11104                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11105
11106                 g_assert (klass->generic_container->type_params [i].param.owner);
11107         }
11108
11109         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11110 }
11111
11112 /*
11113  * mono_reflection_create_internal_class:
11114  * @tb: a TypeBuilder object
11115  *
11116  * Actually create the MonoClass that is associated with the TypeBuilder.
11117  */
11118 void
11119 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11120 {
11121         MonoClass *klass;
11122
11123         klass = mono_class_from_mono_type (tb->type.type);
11124
11125         mono_loader_lock ();
11126         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11127                 MonoReflectionFieldBuilder *fb;
11128                 MonoClass *ec;
11129                 MonoType *enum_basetype;
11130
11131                 g_assert (tb->fields != NULL);
11132                 g_assert (mono_array_length (tb->fields) >= 1);
11133
11134                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11135
11136                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11137                         mono_loader_unlock ();
11138                         return;
11139                 }
11140
11141                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11142                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11143                 if (!klass->element_class)
11144                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11145
11146                 /*
11147                  * get the element_class from the current corlib.
11148                  */
11149                 ec = default_class_from_mono_type (enum_basetype);
11150                 klass->instance_size = ec->instance_size;
11151                 klass->size_inited = 1;
11152                 /* 
11153                  * this is almost safe to do with enums and it's needed to be able
11154                  * to create objects of the enum type (for use in SetConstant).
11155                  */
11156                 /* FIXME: Does this mean enums can't have method overrides ? */
11157                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11158         }
11159         mono_loader_unlock ();
11160 }
11161
11162 static MonoMarshalSpec*
11163 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11164                                                                 MonoReflectionMarshal *minfo)
11165 {
11166         MonoMarshalSpec *res;
11167
11168         res = image_g_new0 (image, MonoMarshalSpec, 1);
11169         res->native = (MonoMarshalNative)minfo->type;
11170
11171         switch (minfo->type) {
11172         case MONO_NATIVE_LPARRAY:
11173                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11174                 if (minfo->has_size) {
11175                         res->data.array_data.param_num = minfo->param_num;
11176                         res->data.array_data.num_elem = minfo->count;
11177                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11178                 }
11179                 else {
11180                         res->data.array_data.param_num = -1;
11181                         res->data.array_data.num_elem = -1;
11182                         res->data.array_data.elem_mult = -1;
11183                 }
11184                 break;
11185
11186         case MONO_NATIVE_BYVALTSTR:
11187         case MONO_NATIVE_BYVALARRAY:
11188                 res->data.array_data.num_elem = minfo->count;
11189                 break;
11190
11191         case MONO_NATIVE_CUSTOM:
11192                 if (minfo->marshaltyperef)
11193                         res->data.custom_data.custom_name =
11194                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11195                 if (minfo->mcookie)
11196                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11197                 break;
11198
11199         default:
11200                 break;
11201         }
11202
11203         return res;
11204 }
11205 #endif /* !DISABLE_REFLECTION_EMIT */
11206
11207 MonoReflectionMarshalAsAttribute*
11208 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11209                                                         MonoMarshalSpec *spec, MonoError *error)
11210 {
11211         MonoReflectionType *rt;
11212         MonoReflectionMarshalAsAttribute *minfo;
11213         MonoType *mtype;
11214
11215         mono_error_init (error);
11216         
11217         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11218         if (!minfo)
11219                 return NULL;
11220         minfo->utype = spec->native;
11221
11222         switch (minfo->utype) {
11223         case MONO_NATIVE_LPARRAY:
11224                 minfo->array_subtype = spec->data.array_data.elem_type;
11225                 minfo->size_const = spec->data.array_data.num_elem;
11226                 if (spec->data.array_data.param_num != -1)
11227                         minfo->size_param_index = spec->data.array_data.param_num;
11228                 break;
11229
11230         case MONO_NATIVE_BYVALTSTR:
11231         case MONO_NATIVE_BYVALARRAY:
11232                 minfo->size_const = spec->data.array_data.num_elem;
11233                 break;
11234
11235         case MONO_NATIVE_CUSTOM:
11236                 if (spec->data.custom_data.custom_name) {
11237                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11238                         if (mtype) {
11239                                 rt = mono_type_get_object_checked (domain, mtype, error);
11240                                 if (!rt)
11241                                         return NULL;
11242
11243                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11244                         }
11245
11246                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11247                 }
11248                 if (spec->data.custom_data.cookie)
11249                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11250                 break;
11251
11252         default:
11253                 break;
11254         }
11255
11256         return minfo;
11257 }
11258
11259 #ifndef DISABLE_REFLECTION_EMIT
11260 static MonoMethod*
11261 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11262                                          ReflectionMethodBuilder *rmb,
11263                                          MonoMethodSignature *sig)
11264 {
11265         MonoError error;
11266         MonoMethod *m;
11267         MonoMethodWrapper *wrapperm;
11268         MonoMarshalSpec **specs;
11269         MonoReflectionMethodAux *method_aux;
11270         MonoImage *image;
11271         gboolean dynamic;
11272         int i;
11273
11274         mono_error_init (&error);
11275         /*
11276          * Methods created using a MethodBuilder should have their memory allocated
11277          * inside the image mempool, while dynamic methods should have their memory
11278          * malloc'd.
11279          */
11280         dynamic = rmb->refs != NULL;
11281         image = dynamic ? NULL : klass->image;
11282
11283         if (!dynamic)
11284                 g_assert (!klass->generic_class);
11285
11286         mono_loader_lock ();
11287
11288         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11289                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11290                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11291         else
11292                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11293
11294         wrapperm = (MonoMethodWrapper*)m;
11295
11296         m->dynamic = dynamic;
11297         m->slot = -1;
11298         m->flags = rmb->attrs;
11299         m->iflags = rmb->iattrs;
11300         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11301         m->klass = klass;
11302         m->signature = sig;
11303         m->sre_method = TRUE;
11304         m->skip_visibility = rmb->skip_visibility;
11305         if (rmb->table_idx)
11306                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11307
11308         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11309                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11310                         m->string_ctor = 1;
11311
11312                 m->signature->pinvoke = 1;
11313         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11314                 m->signature->pinvoke = 1;
11315
11316                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11317
11318                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11319                 g_assert (mono_error_ok (&error));
11320                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11321                 g_assert (mono_error_ok (&error));
11322                 
11323                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11324
11325                 if (image_is_dynamic (klass->image))
11326                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11327
11328                 mono_loader_unlock ();
11329
11330                 return m;
11331         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11332                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11333                 MonoMethodHeader *header;
11334                 guint32 code_size;
11335                 gint32 max_stack, i;
11336                 gint32 num_locals = 0;
11337                 gint32 num_clauses = 0;
11338                 guint8 *code;
11339
11340                 if (rmb->ilgen) {
11341                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11342                         code_size = rmb->ilgen->code_len;
11343                         max_stack = rmb->ilgen->max_stack;
11344                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11345                         if (rmb->ilgen->ex_handlers)
11346                                 num_clauses = method_count_clauses (rmb->ilgen);
11347                 } else {
11348                         if (rmb->code) {
11349                                 code = mono_array_addr (rmb->code, guint8, 0);
11350                                 code_size = mono_array_length (rmb->code);
11351                                 /* we probably need to run a verifier on the code... */
11352                                 max_stack = 8; 
11353                         }
11354                         else {
11355                                 code = NULL;
11356                                 code_size = 0;
11357                                 max_stack = 8;
11358                         }
11359                 }
11360
11361                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11362                 header->code_size = code_size;
11363                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11364                 memcpy ((char*)header->code, code, code_size);
11365                 header->max_stack = max_stack;
11366                 header->init_locals = rmb->init_locals;
11367                 header->num_locals = num_locals;
11368
11369                 for (i = 0; i < num_locals; ++i) {
11370                         MonoReflectionLocalBuilder *lb = 
11371                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11372
11373                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11374                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11375                 }
11376
11377                 header->num_clauses = num_clauses;
11378                 if (num_clauses) {
11379                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11380                                  rmb->ilgen, num_clauses);
11381                 }
11382
11383                 wrapperm->header = header;
11384         }
11385
11386         if (rmb->generic_params) {
11387                 int count = mono_array_length (rmb->generic_params);
11388                 MonoGenericContainer *container = rmb->generic_container;
11389
11390                 g_assert (container);
11391
11392                 container->type_argc = count;
11393                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11394                 container->owner.method = m;
11395                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11396
11397                 m->is_generic = TRUE;
11398                 mono_method_set_generic_container (m, container);
11399
11400                 for (i = 0; i < count; i++) {
11401                         MonoReflectionGenericParam *gp =
11402                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11403                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11404                         container->type_params [i] = *param;
11405                 }
11406
11407                 /*
11408                  * The method signature might have pointers to generic parameters that belong to other methods.
11409                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11410                  * generic parameters.
11411                  */
11412                 for (i = 0; i < m->signature->param_count; ++i) {
11413                         MonoType *t = m->signature->params [i];
11414                         if (t->type == MONO_TYPE_MVAR) {
11415                                 MonoGenericParam *gparam =  t->data.generic_param;
11416                                 if (gparam->num < count) {
11417                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11418                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11419                                 }
11420
11421                         }
11422                 }
11423
11424                 if (klass->generic_container) {
11425                         container->parent = klass->generic_container;
11426                         container->context.class_inst = klass->generic_container->context.class_inst;
11427                 }
11428                 container->context.method_inst = mono_get_shared_generic_inst (container);
11429         }
11430
11431         if (rmb->refs) {
11432                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11433                 int i;
11434                 void **data;
11435
11436                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11437
11438                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11439                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11440                 for (i = 0; i < rmb->nrefs; ++i)
11441                         data [i + 1] = rmb->refs [i];
11442         }
11443
11444         method_aux = NULL;
11445
11446         /* Parameter info */
11447         if (rmb->pinfo) {
11448                 if (!method_aux)
11449                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11450                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11451                 for (i = 0; i <= m->signature->param_count; ++i) {
11452                         MonoReflectionParamBuilder *pb;
11453                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11454                                 if ((i > 0) && (pb->attrs)) {
11455                                         /* Make a copy since it might point to a shared type structure */
11456                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11457                                         m->signature->params [i - 1]->attrs = pb->attrs;
11458                                 }
11459
11460                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11461                                         MonoDynamicImage *assembly;
11462                                         guint32 idx, len;
11463                                         MonoTypeEnum def_type;
11464                                         char *p;
11465                                         const char *p2;
11466
11467                                         if (!method_aux->param_defaults) {
11468                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11469                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11470                                         }
11471                                         assembly = (MonoDynamicImage*)klass->image;
11472                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11473                                         /* Copy the data from the blob since it might get realloc-ed */
11474                                         p = assembly->blob.data + idx;
11475                                         len = mono_metadata_decode_blob_size (p, &p2);
11476                                         len += p2 - p;
11477                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11478                                         method_aux->param_default_types [i] = def_type;
11479                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11480                                 }
11481
11482                                 if (pb->name) {
11483                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11484                                         g_assert (mono_error_ok (&error));
11485                                 }
11486                                 if (pb->cattrs) {
11487                                         if (!method_aux->param_cattr)
11488                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11489                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11490                                 }
11491                         }
11492                 }
11493         }
11494
11495         /* Parameter marshalling */
11496         specs = NULL;
11497         if (rmb->pinfo)         
11498                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11499                         MonoReflectionParamBuilder *pb;
11500                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11501                                 if (pb->marshal_info) {
11502                                         if (specs == NULL)
11503                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11504                                         specs [pb->position] = 
11505                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11506                                 }
11507                         }
11508                 }
11509         if (specs != NULL) {
11510                 if (!method_aux)
11511                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11512                 method_aux->param_marshall = specs;
11513         }
11514
11515         if (image_is_dynamic (klass->image) && method_aux)
11516                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11517
11518         mono_loader_unlock ();
11519
11520         return m;
11521 }       
11522
11523 static MonoMethod*
11524 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11525 {
11526         ReflectionMethodBuilder rmb;
11527         MonoMethodSignature *sig;
11528
11529         mono_loader_lock ();
11530         sig = ctor_builder_to_signature (klass->image, mb);
11531         mono_loader_unlock ();
11532
11533         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11534                 return NULL;
11535
11536         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11537         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11538
11539         /* If we are in a generic class, we might be called multiple times from inflate_method */
11540         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11541                 /* ilgen is no longer needed */
11542                 mb->ilgen = NULL;
11543         }
11544
11545         return mb->mhandle;
11546 }
11547
11548 static MonoMethod*
11549 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11550 {
11551         ReflectionMethodBuilder rmb;
11552         MonoMethodSignature *sig;
11553
11554         mono_error_init (error);
11555
11556         mono_loader_lock ();
11557         sig = method_builder_to_signature (klass->image, mb);
11558         mono_loader_unlock ();
11559
11560         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11561                 return NULL;
11562
11563         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11564         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11565
11566         /* If we are in a generic class, we might be called multiple times from inflate_method */
11567         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11568                 /* ilgen is no longer needed */
11569                 mb->ilgen = NULL;
11570         }
11571         return mb->mhandle;
11572 }
11573
11574 static MonoClassField*
11575 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11576 {
11577         MonoClassField *field;
11578         MonoType *custom;
11579         MonoError error;
11580
11581         field = g_new0 (MonoClassField, 1);
11582
11583         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11584         g_assert (mono_error_ok (&error));
11585         if (fb->attrs || fb->modreq || fb->modopt) {
11586                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11587                 field->type->attrs = fb->attrs;
11588
11589                 g_assert (image_is_dynamic (klass->image));
11590                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11591                 g_free (field->type);
11592                 field->type = mono_metadata_type_dup (klass->image, custom);
11593                 g_free (custom);
11594         } else {
11595                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11596         }
11597         if (fb->offset != -1)
11598                 field->offset = fb->offset;
11599         field->parent = klass;
11600         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11601
11602         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11603
11604         return field;
11605 }
11606 #endif
11607
11608 MonoType*
11609 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11610 {
11611         MonoClass *klass;
11612         MonoReflectionTypeBuilder *tb = NULL;
11613         gboolean is_dynamic = FALSE;
11614         MonoClass *geninst;
11615
11616         mono_loader_lock ();
11617
11618         if (is_sre_type_builder (mono_object_class (type))) {
11619                 tb = (MonoReflectionTypeBuilder *) type;
11620
11621                 is_dynamic = TRUE;
11622         } else if (is_sre_generic_instance (mono_object_class (type))) {
11623                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11624                 MonoReflectionType *gtd = rgi->generic_type;
11625
11626                 if (is_sre_type_builder (mono_object_class (gtd))) {
11627                         tb = (MonoReflectionTypeBuilder *)gtd;
11628                         is_dynamic = TRUE;
11629                 }
11630         }
11631
11632         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11633         if (tb && tb->generic_container)
11634                 mono_reflection_create_generic_class (tb);
11635
11636         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11637         if (!klass->generic_container) {
11638                 mono_loader_unlock ();
11639                 return NULL;
11640         }
11641
11642         if (klass->wastypebuilder) {
11643                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11644
11645                 is_dynamic = TRUE;
11646         }
11647
11648         mono_loader_unlock ();
11649
11650         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11651
11652         return &geninst->byval_arg;
11653 }
11654
11655 MonoClass*
11656 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11657 {
11658         MonoGenericClass *gclass;
11659         MonoGenericInst *inst;
11660
11661         g_assert (klass->generic_container);
11662
11663         inst = mono_metadata_get_generic_inst (type_argc, types);
11664         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11665
11666         return mono_generic_class_get_class (gclass);
11667 }
11668
11669 MonoReflectionMethod*
11670 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11671 {
11672         MonoError error;
11673         MonoClass *klass;
11674         MonoMethod *method, *inflated;
11675         MonoMethodInflated *imethod;
11676         MonoGenericContext tmp_context;
11677         MonoGenericInst *ginst;
11678         MonoType **type_argv;
11679         int count, i;
11680
11681         /*FIXME but this no longer should happen*/
11682         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11683 #ifndef DISABLE_REFLECTION_EMIT
11684                 MonoReflectionMethodBuilder *mb = NULL;
11685                 MonoReflectionTypeBuilder *tb;
11686                 MonoClass *klass;
11687
11688                 mb = (MonoReflectionMethodBuilder *) rmethod;
11689                 tb = (MonoReflectionTypeBuilder *) mb->type;
11690                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11691
11692                 method = methodbuilder_to_mono_method (klass, mb, &error);
11693                 if (!method)
11694                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11695 #else
11696                 g_assert_not_reached ();
11697                 method = NULL;
11698 #endif
11699         } else {
11700                 method = rmethod->method;
11701         }
11702
11703         klass = method->klass;
11704
11705         if (method->is_inflated)
11706                 method = ((MonoMethodInflated *) method)->declaring;
11707
11708         count = mono_method_signature (method)->generic_param_count;
11709         if (count != mono_array_length (types))
11710                 return NULL;
11711
11712         type_argv = g_new0 (MonoType *, count);
11713         for (i = 0; i < count; i++) {
11714                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11715                 type_argv [i] = mono_reflection_type_get_handle (garg);
11716         }
11717         ginst = mono_metadata_get_generic_inst (count, type_argv);
11718         g_free (type_argv);
11719
11720         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11721         tmp_context.method_inst = ginst;
11722
11723         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11724         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11725         imethod = (MonoMethodInflated *) inflated;
11726
11727         /*FIXME but I think this is no longer necessary*/
11728         if (image_is_dynamic (method->klass->image)) {
11729                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11730                 /*
11731                  * This table maps metadata structures representing inflated methods/fields
11732                  * to the reflection objects representing their generic definitions.
11733                  */
11734                 mono_image_lock ((MonoImage*)image);
11735                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11736                 mono_image_unlock ((MonoImage*)image);
11737         }
11738
11739         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11740                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11741         
11742         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11743         mono_error_raise_exception (&error); /* FIXME don't raise here */
11744         return ret;
11745 }
11746
11747 #ifndef DISABLE_REFLECTION_EMIT
11748
11749 static MonoMethod *
11750 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11751 {
11752         MonoMethodInflated *imethod;
11753         MonoGenericContext *context;
11754         int i;
11755
11756         /*
11757          * With generic code sharing the klass might not be inflated.
11758          * This can happen because classes inflated with their own
11759          * type arguments are "normalized" to the uninflated class.
11760          */
11761         if (!klass->generic_class)
11762                 return method;
11763
11764         context = mono_class_get_context (klass);
11765
11766         if (klass->method.count && klass->methods) {
11767                 /* Find the already created inflated method */
11768                 for (i = 0; i < klass->method.count; ++i) {
11769                         g_assert (klass->methods [i]->is_inflated);
11770                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11771                                 break;
11772                 }
11773                 g_assert (i < klass->method.count);
11774                 imethod = (MonoMethodInflated*)klass->methods [i];
11775         } else {
11776                 MonoError error;
11777                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11778                 mono_error_assert_ok (&error);
11779         }
11780
11781         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11782                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11783
11784                 mono_image_lock ((MonoImage*)image);
11785                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11786                 mono_image_unlock ((MonoImage*)image);
11787         }
11788         return (MonoMethod *) imethod;
11789 }
11790
11791 static MonoMethod *
11792 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11793 {
11794         MonoMethod *method;
11795         MonoClass *gklass;
11796
11797         mono_error_init (error);
11798
11799         MonoClass *type_class = mono_object_class (type);
11800
11801         if (is_sre_generic_instance (type_class)) {
11802                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11803                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11804         } else if (is_sre_type_builder (type_class)) {
11805                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11806         } else if (type->type) {
11807                 gklass = mono_class_from_mono_type (type->type);
11808                 gklass = mono_class_get_generic_type_definition (gklass);
11809         } else {
11810                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11811         }
11812
11813         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11814                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11815                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11816                 else {
11817                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11818                         if (!method)
11819                                 return NULL;
11820                 }
11821         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11822                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11823                 if (!method)
11824                         return NULL;
11825         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11826                 method = ((MonoReflectionMethod *) obj)->method;
11827         else {
11828                 method = NULL; /* prevent compiler warning */
11829                 g_error ("can't handle type %s", obj->vtable->klass->name);
11830         }
11831
11832         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11833 }
11834
11835 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11836 void
11837 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11838 {
11839         MonoGenericClass *gclass;
11840         MonoDynamicGenericClass *dgclass;
11841         MonoClass *klass, *gklass;
11842         MonoType *gtype;
11843         int i;
11844
11845         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11846         klass = mono_class_from_mono_type (gtype);
11847         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11848         gclass = gtype->data.generic_class;
11849
11850         if (!gclass->is_dynamic)
11851                 return;
11852
11853         dgclass = (MonoDynamicGenericClass *) gclass;
11854
11855         if (dgclass->initialized)
11856                 return;
11857
11858         gklass = gclass->container_class;
11859         mono_class_init (gklass);
11860
11861         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11862
11863         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11864         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11865         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11866
11867         for (i = 0; i < dgclass->count_fields; i++) {
11868                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11869                 MonoClassField *field, *inflated_field = NULL;
11870
11871                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11872                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11873                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11874                         field = ((MonoReflectionField *) obj)->field;
11875                 else {
11876                         field = NULL; /* prevent compiler warning */
11877                         g_assert_not_reached ();
11878                 }
11879
11880                 dgclass->fields [i] = *field;
11881                 dgclass->fields [i].parent = klass;
11882                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11883                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11884                 dgclass->field_generic_types [i] = field->type;
11885                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11886                 dgclass->field_objects [i] = obj;
11887
11888                 if (inflated_field) {
11889                         g_free (inflated_field);
11890                 } else {
11891                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11892                 }
11893         }
11894
11895         dgclass->initialized = TRUE;
11896 }
11897
11898 void
11899 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11900 {
11901         MonoDynamicGenericClass *dgclass;
11902         int i;
11903
11904         g_assert (gclass->is_dynamic);
11905
11906         dgclass = (MonoDynamicGenericClass *)gclass;
11907
11908         for (i = 0; i < dgclass->count_fields; ++i) {
11909                 MonoClassField *field = dgclass->fields + i;
11910                 mono_metadata_free_type (field->type);
11911                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11912         }
11913 }
11914
11915 static void
11916 fix_partial_generic_class (MonoClass *klass)
11917 {
11918         MonoClass *gklass = klass->generic_class->container_class;
11919         MonoDynamicGenericClass *dgclass;
11920         int i;
11921
11922         if (klass->wastypebuilder)
11923                 return;
11924
11925         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11926         if (klass->parent != gklass->parent) {
11927                 MonoError error;
11928                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11929                 if (mono_error_ok (&error)) {
11930                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11931                         mono_metadata_free_type (parent_type);
11932                         if (parent != klass->parent) {
11933                                 /*fool mono_class_setup_parent*/
11934                                 klass->supertypes = NULL;
11935                                 mono_class_setup_parent (klass, parent);
11936                         }
11937                 } else {
11938                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11939                         mono_error_cleanup (&error);
11940                         if (gklass->wastypebuilder)
11941                                 klass->wastypebuilder = TRUE;
11942                         return;
11943                 }
11944         }
11945
11946         if (!dgclass->initialized)
11947                 return;
11948
11949         if (klass->method.count != gklass->method.count) {
11950                 klass->method.count = gklass->method.count;
11951                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11952
11953                 for (i = 0; i < klass->method.count; i++) {
11954                         MonoError error;
11955                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11956                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11957                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11958                 }
11959         }
11960
11961         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11962                 klass->interface_count = gklass->interface_count;
11963                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11964                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11965
11966                 for (i = 0; i < gklass->interface_count; ++i) {
11967                         MonoError error;
11968                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11969                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11970                         mono_metadata_free_type (iface_type);
11971
11972                         ensure_runtime_vtable (klass->interfaces [i], &error);
11973                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11974                 }
11975                 klass->interfaces_inited = 1;
11976         }
11977
11978         if (klass->field.count != gklass->field.count) {
11979                 klass->field.count = gklass->field.count;
11980                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11981
11982                 for (i = 0; i < klass->field.count; i++) {
11983                         klass->fields [i] = gklass->fields [i];
11984                         klass->fields [i].parent = klass;
11985                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11986                 }
11987         }
11988
11989         /*We can only finish with this klass once it's parent has as well*/
11990         if (gklass->wastypebuilder)
11991                 klass->wastypebuilder = TRUE;
11992         return;
11993 }
11994
11995 /**
11996  * ensure_generic_class_runtime_vtable:
11997  * @klass a generic class
11998  * @error set on error
11999  *
12000  * Ensures that the generic container of @klass has a vtable and
12001  * returns TRUE on success.  On error returns FALSE and sets @error.
12002  */
12003 static gboolean
12004 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12005 {
12006         MonoClass *gklass = klass->generic_class->container_class;
12007
12008         mono_error_init (error);
12009
12010         if (!ensure_runtime_vtable (gklass, error))
12011                 return FALSE;
12012
12013         fix_partial_generic_class (klass);
12014
12015         return TRUE;
12016 }
12017
12018 /**
12019  * ensure_runtime_vtable:
12020  * @klass the class
12021  * @error set on error
12022  *
12023  * Ensures that @klass has a vtable and returns TRUE on success. On
12024  * error returns FALSE and sets @error.
12025  */
12026 static gboolean
12027 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12028 {
12029         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12030         int i, num, j;
12031
12032         mono_error_init (error);
12033
12034         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12035                 return TRUE;
12036         if (klass->parent)
12037                 if (!ensure_runtime_vtable (klass->parent, error))
12038                         return FALSE;
12039
12040         if (tb) {
12041                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12042                 num += tb->num_methods;
12043                 klass->method.count = num;
12044                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12045                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12046                 for (i = 0; i < num; ++i) {
12047                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12048                         if (!ctor)
12049                                 return FALSE;
12050                         klass->methods [i] = ctor;
12051                 }
12052                 num = tb->num_methods;
12053                 j = i;
12054                 for (i = 0; i < num; ++i) {
12055                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12056                         if (!meth)
12057                                 return FALSE;
12058                         klass->methods [j++] = meth;
12059                 }
12060         
12061                 if (tb->interfaces) {
12062                         klass->interface_count = mono_array_length (tb->interfaces);
12063                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12064                         for (i = 0; i < klass->interface_count; ++i) {
12065                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
12066                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12067                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12068                                         return FALSE;
12069                         }
12070                         klass->interfaces_inited = 1;
12071                 }
12072         } else if (klass->generic_class){
12073                 if (!ensure_generic_class_runtime_vtable (klass, error))
12074                         return FALSE;
12075         }
12076
12077         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12078                 int slot_num = 0;
12079                 for (i = 0; i < klass->method.count; ++i) {
12080                         MonoMethod *im = klass->methods [i];
12081                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12082                                 im->slot = slot_num++;
12083                 }
12084                 
12085                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12086                 mono_class_setup_interface_offsets (klass);
12087                 mono_class_setup_interface_id (klass);
12088         }
12089
12090         /*
12091          * The generic vtable is needed even if image->run is not set since some
12092          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12093          * method->slot being defined.
12094          */
12095
12096         /* 
12097          * tb->methods could not be freed since it is used for determining 
12098          * overrides during dynamic vtable construction.
12099          */
12100
12101         return TRUE;
12102 }
12103
12104 static MonoMethod*
12105 mono_reflection_method_get_handle (MonoObject *method)
12106 {
12107         MonoError error;
12108         MonoClass *klass = mono_object_class (method);
12109         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12110                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12111                 return sr_method->method;
12112         }
12113         if (is_sre_method_builder (klass)) {
12114                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12115                 return mb->mhandle;
12116         }
12117         if (is_sre_method_on_tb_inst (klass)) {
12118                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12119                 MonoMethod *result;
12120                 /*FIXME move this to a proper method and unify with resolve_object*/
12121                 if (m->method_args) {
12122                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12123                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12124                 } else {
12125                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12126                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12127                         MonoMethod *mono_method;
12128
12129                         if (is_sre_method_builder (mono_object_class (m->mb)))
12130                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12131                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12132                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12133                         else
12134                                 g_error ("resolve_object:: can't handle a MTBI with base_method of type %s", mono_type_get_full_name (mono_object_class (m->mb)));
12135
12136                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12137                 }
12138                 return result;
12139         }
12140
12141         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12142         return NULL;
12143 }
12144
12145 void
12146 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12147 {
12148         MonoReflectionTypeBuilder *tb;
12149         int i, j, onum;
12150         MonoReflectionMethod *m;
12151
12152         *overrides = NULL;
12153         *num_overrides = 0;
12154
12155         g_assert (image_is_dynamic (klass->image));
12156
12157         if (!mono_class_get_ref_info (klass))
12158                 return;
12159
12160         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12161
12162         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12163
12164         onum = 0;
12165         if (tb->methods) {
12166                 for (i = 0; i < tb->num_methods; ++i) {
12167                         MonoReflectionMethodBuilder *mb = 
12168                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12169                         if (mb->override_methods)
12170                                 onum += mono_array_length (mb->override_methods);
12171                 }
12172         }
12173
12174         if (onum) {
12175                 *overrides = g_new0 (MonoMethod*, onum * 2);
12176
12177                 onum = 0;
12178                 for (i = 0; i < tb->num_methods; ++i) {
12179                         MonoReflectionMethodBuilder *mb = 
12180                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12181                         if (mb->override_methods) {
12182                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12183                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12184
12185                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12186                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12187
12188                                         g_assert (mb->mhandle);
12189
12190                                         onum ++;
12191                                 }
12192                         }
12193                 }
12194         }
12195
12196         *num_overrides = onum;
12197 }
12198
12199 static void
12200 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12201 {
12202         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12203         MonoReflectionFieldBuilder *fb;
12204         MonoClassField *field;
12205         MonoImage *image = klass->image;
12206         const char *p, *p2;
12207         int i;
12208         guint32 len, idx, real_size = 0;
12209
12210         klass->field.count = tb->num_fields;
12211         klass->field.first = 0;
12212
12213         mono_error_init (error);
12214
12215         if (tb->class_size) {
12216                 if ((tb->packing_size & 0xffffff00) != 0) {
12217                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12218                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12219                         return;
12220                 }
12221                 klass->packing_size = tb->packing_size;
12222                 real_size = klass->instance_size + tb->class_size;
12223         }
12224
12225         if (!klass->field.count) {
12226                 klass->instance_size = MAX (klass->instance_size, real_size);
12227                 return;
12228         }
12229         
12230         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12231         mono_class_alloc_ext (klass);
12232         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12233         /*
12234         This is, guess what, a hack.
12235         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12236         On the static path no field class is resolved, only types are built. This is the right thing to do
12237         but we suck.
12238         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12239         */
12240         klass->size_inited = 1;
12241
12242         for (i = 0; i < klass->field.count; ++i) {
12243                 MonoArray *rva_data;
12244                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12245                 field = &klass->fields [i];
12246                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12247                 if (!mono_error_ok (error))
12248                         return;
12249                 if (fb->attrs) {
12250                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12251                         field->type->attrs = fb->attrs;
12252                 } else {
12253                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12254                 }
12255
12256                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12257                         char *base = mono_array_addr (rva_data, char, 0);
12258                         size_t size = mono_array_length (rva_data);
12259                         char *data = (char *)mono_image_alloc (klass->image, size);
12260                         memcpy (data, base, size);
12261                         klass->ext->field_def_values [i].data = data;
12262                 }
12263                 if (fb->offset != -1)
12264                         field->offset = fb->offset;
12265                 field->parent = klass;
12266                 fb->handle = field;
12267                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12268
12269                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12270                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12271                 }
12272                 if (fb->def_value) {
12273                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12274                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12275                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12276                         /* Copy the data from the blob since it might get realloc-ed */
12277                         p = assembly->blob.data + idx;
12278                         len = mono_metadata_decode_blob_size (p, &p2);
12279                         len += p2 - p;
12280                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12281                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12282                 }
12283         }
12284
12285         klass->instance_size = MAX (klass->instance_size, real_size);
12286         mono_class_layout_fields (klass);
12287 }
12288
12289 static void
12290 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12291 {
12292         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12293         MonoReflectionPropertyBuilder *pb;
12294         MonoImage *image = klass->image;
12295         MonoProperty *properties;
12296         int i;
12297
12298         mono_error_init (error);
12299
12300         if (!klass->ext)
12301                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12302
12303         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12304         klass->ext->property.first = 0;
12305
12306         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12307         klass->ext->properties = properties;
12308         for (i = 0; i < klass->ext->property.count; ++i) {
12309                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12310                 properties [i].parent = klass;
12311                 properties [i].attrs = pb->attrs;
12312                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12313                 if (!mono_error_ok (error))
12314                         return;
12315                 if (pb->get_method)
12316                         properties [i].get = pb->get_method->mhandle;
12317                 if (pb->set_method)
12318                         properties [i].set = pb->set_method->mhandle;
12319
12320                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12321                 if (pb->def_value) {
12322                         guint32 len, idx;
12323                         const char *p, *p2;
12324                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12325                         if (!klass->ext->prop_def_values)
12326                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12327                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12328                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12329                         /* Copy the data from the blob since it might get realloc-ed */
12330                         p = assembly->blob.data + idx;
12331                         len = mono_metadata_decode_blob_size (p, &p2);
12332                         len += p2 - p;
12333                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12334                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12335                 }
12336         }
12337 }
12338
12339 MonoReflectionEvent *
12340 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12341 {
12342         MonoError error;
12343         MonoEvent *event = g_new0 (MonoEvent, 1);
12344         MonoClass *klass;
12345
12346         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12347
12348         event->parent = klass;
12349         event->attrs = eb->attrs;
12350         event->name = mono_string_to_utf8 (eb->name);
12351         if (eb->add_method)
12352                 event->add = eb->add_method->mhandle;
12353         if (eb->remove_method)
12354                 event->remove = eb->remove_method->mhandle;
12355         if (eb->raise_method)
12356                 event->raise = eb->raise_method->mhandle;
12357
12358 #ifndef MONO_SMALL_CONFIG
12359         if (eb->other_methods) {
12360                 int j;
12361                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12362                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12363                         MonoReflectionMethodBuilder *mb = 
12364                                 mono_array_get (eb->other_methods,
12365                                                 MonoReflectionMethodBuilder*, j);
12366                         event->other [j] = mb->mhandle;
12367                 }
12368         }
12369 #endif
12370
12371         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12372         mono_error_raise_exception (&error); /* FIXME don't raise here */
12373         return ev_obj;
12374 }
12375
12376 static void
12377 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12378 {
12379         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12380         MonoReflectionEventBuilder *eb;
12381         MonoImage *image = klass->image;
12382         MonoEvent *events;
12383         int i;
12384
12385         mono_error_init (error);
12386
12387         if (!klass->ext)
12388                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12389
12390         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12391         klass->ext->event.first = 0;
12392
12393         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12394         klass->ext->events = events;
12395         for (i = 0; i < klass->ext->event.count; ++i) {
12396                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12397                 events [i].parent = klass;
12398                 events [i].attrs = eb->attrs;
12399                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12400                 if (!mono_error_ok (error))
12401                         return;
12402                 if (eb->add_method)
12403                         events [i].add = eb->add_method->mhandle;
12404                 if (eb->remove_method)
12405                         events [i].remove = eb->remove_method->mhandle;
12406                 if (eb->raise_method)
12407                         events [i].raise = eb->raise_method->mhandle;
12408
12409 #ifndef MONO_SMALL_CONFIG
12410                 if (eb->other_methods) {
12411                         int j;
12412                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12413                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12414                                 MonoReflectionMethodBuilder *mb = 
12415                                         mono_array_get (eb->other_methods,
12416                                                                         MonoReflectionMethodBuilder*, j);
12417                                 events [i].other [j] = mb->mhandle;
12418                         }
12419                 }
12420 #endif
12421                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12422         }
12423 }
12424
12425 static gboolean
12426 remove_instantiations_of_and_ensure_contents (gpointer key,
12427                                                   gpointer value,
12428                                                   gpointer user_data)
12429 {
12430         MonoType *type = (MonoType*)key;
12431         MonoClass *klass = (MonoClass*)user_data;
12432
12433         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12434                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12435                 return TRUE;
12436         } else
12437                 return FALSE;
12438 }
12439
12440 static void
12441 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12442 {
12443         mono_error_init (error);
12444         int i;
12445
12446         if (!arr)
12447                 return;
12448
12449         for (i = 0; i < mono_array_length (arr); ++i) {
12450                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12451                 if (!mono_error_ok (error))
12452                         break;
12453         }
12454 }
12455
12456 MonoReflectionType*
12457 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12458 {
12459         MonoError error;
12460         MonoClass *klass;
12461         MonoDomain* domain;
12462         MonoReflectionType* res;
12463         int i, j;
12464
12465         domain = mono_object_domain (tb);
12466         klass = mono_class_from_mono_type (tb->type.type);
12467
12468         /*
12469          * Check for user defined Type subclasses.
12470          */
12471         RESOLVE_TYPE (tb->parent, &error);
12472         mono_error_raise_exception (&error); /* FIXME don't raise here */
12473         check_array_for_usertypes (tb->interfaces, &error);
12474         mono_error_raise_exception (&error); /*FIXME don't raise here */
12475         if (tb->fields) {
12476                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12477                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12478                         if (fb) {
12479                                 RESOLVE_TYPE (fb->type, &error);
12480                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12481                                 check_array_for_usertypes (fb->modreq, &error);
12482                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12483                                 check_array_for_usertypes (fb->modopt, &error);
12484                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12485                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12486                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12487                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12488                                 }
12489                         }
12490                 }
12491         }
12492         if (tb->methods) {
12493                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12494                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12495                         if (mb) {
12496                                 RESOLVE_TYPE (mb->rtype, &error);
12497                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12498                                 check_array_for_usertypes (mb->return_modreq, &error);
12499                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12500                                 check_array_for_usertypes (mb->return_modopt, &error);
12501                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12502                                 check_array_for_usertypes (mb->parameters, &error);
12503                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12504                                 if (mb->param_modreq)
12505                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12506                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12507                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12508                                         }
12509                                 if (mb->param_modopt)
12510                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12511                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12512                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12513                                         }
12514                         }
12515                 }
12516         }
12517         if (tb->ctors) {
12518                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12519                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12520                         if (mb) {
12521                                 check_array_for_usertypes (mb->parameters, &error);
12522                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12523                                 if (mb->param_modreq)
12524                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12525                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12526                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12527                                         }
12528                                 if (mb->param_modopt)
12529                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12530                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12531                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12532                                         }
12533                         }
12534                 }
12535         }
12536
12537         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12538
12539         /* 
12540          * we need to lock the domain because the lock will be taken inside
12541          * So, we need to keep the locking order correct.
12542          */
12543         mono_loader_lock ();
12544         mono_domain_lock (domain);
12545         if (klass->wastypebuilder) {
12546                 mono_domain_unlock (domain);
12547                 mono_loader_unlock ();
12548
12549                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12550                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12551
12552                 return res;
12553         }
12554         /*
12555          * Fields to set in klass:
12556          * the various flags: delegate/unicode/contextbound etc.
12557          */
12558         klass->flags = tb->attrs;
12559         klass->has_cctor = 1;
12560         klass->has_finalize = 1;
12561         klass->has_finalize_inited = 1;
12562
12563         mono_class_setup_parent (klass, klass->parent);
12564         /* fool mono_class_setup_supertypes */
12565         klass->supertypes = NULL;
12566         mono_class_setup_supertypes (klass);
12567         mono_class_setup_mono_type (klass);
12568
12569 #if 0
12570         if (!((MonoDynamicImage*)klass->image)->run) {
12571                 if (klass->generic_container) {
12572                         /* FIXME: The code below can't handle generic classes */
12573                         klass->wastypebuilder = TRUE;
12574                         mono_loader_unlock ();
12575                         mono_domain_unlock (domain);
12576
12577                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12578                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12579
12580                         return res;
12581                 }
12582         }
12583 #endif
12584
12585         /* enums are done right away */
12586         if (!klass->enumtype)
12587                 if (!ensure_runtime_vtable (klass, &error))
12588                         goto failure;
12589
12590         if (tb->subtypes) {
12591                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12592                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12593                         mono_class_alloc_ext (klass);
12594                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
12595                 }
12596         }
12597
12598         klass->nested_classes_inited = TRUE;
12599
12600         /* fields and object layout */
12601         if (klass->parent) {
12602                 if (!klass->parent->size_inited)
12603                         mono_class_init (klass->parent);
12604                 klass->instance_size = klass->parent->instance_size;
12605                 klass->sizes.class_size = 0;
12606                 klass->min_align = klass->parent->min_align;
12607                 /* if the type has no fields we won't call the field_setup
12608                  * routine which sets up klass->has_references.
12609                  */
12610                 klass->has_references |= klass->parent->has_references;
12611         } else {
12612                 klass->instance_size = sizeof (MonoObject);
12613                 klass->min_align = 1;
12614         }
12615
12616         /* FIXME: handle packing_size and instance_size */
12617         typebuilder_setup_fields (klass, &error);
12618         if (!mono_error_ok (&error))
12619                 goto failure;
12620         typebuilder_setup_properties (klass, &error);
12621         if (!mono_error_ok (&error))
12622                 goto failure;
12623
12624         typebuilder_setup_events (klass, &error);
12625         if (!mono_error_ok (&error))
12626                 goto failure;
12627
12628         klass->wastypebuilder = TRUE;
12629
12630         /* 
12631          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12632          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12633          * we want to return normal System.MonoType objects, so clear these out from the cache.
12634          *
12635          * Together with this we must ensure the contents of all instances to match the created type.
12636          */
12637         if (domain->type_hash && klass->generic_container)
12638                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12639
12640         mono_domain_unlock (domain);
12641         mono_loader_unlock ();
12642
12643         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12644                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12645                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12646         }
12647
12648         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12649         mono_error_raise_exception (&error); /* FIXME don't raise here */
12650
12651         g_assert (res != (MonoReflectionType*)tb);
12652
12653         return res;
12654
12655 failure:
12656         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12657         klass->wastypebuilder = TRUE;
12658         mono_domain_unlock (domain);
12659         mono_loader_unlock ();
12660         mono_error_raise_exception (&error);
12661         return NULL;
12662 }
12663
12664 void
12665 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12666 {
12667         MonoGenericParamFull *param;
12668         MonoImage *image;
12669         MonoClass *pklass;
12670         MonoError error;
12671
12672         image = &gparam->tbuilder->module->dynamic_image->image;
12673
12674         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12675
12676         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12677         g_assert (mono_error_ok (&error));
12678         param->param.num = gparam->index;
12679
12680         if (gparam->mbuilder) {
12681                 if (!gparam->mbuilder->generic_container) {
12682                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12683                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12684                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12685                         gparam->mbuilder->generic_container->is_method = TRUE;
12686                         /* 
12687                          * Cannot set owner.method, since the MonoMethod is not created yet.
12688                          * Set the image field instead, so type_in_image () works.
12689                          */
12690                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12691                         gparam->mbuilder->generic_container->owner.image = klass->image;
12692                 }
12693                 param->param.owner = gparam->mbuilder->generic_container;
12694         } else if (gparam->tbuilder) {
12695                 if (!gparam->tbuilder->generic_container) {
12696                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12697                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12698                         gparam->tbuilder->generic_container->owner.klass = klass;
12699                 }
12700                 param->param.owner = gparam->tbuilder->generic_container;
12701         }
12702
12703         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12704
12705         gparam->type.type = &pklass->byval_arg;
12706
12707         mono_class_set_ref_info (pklass, gparam);
12708         mono_image_append_class_to_reflection_info_set (pklass);
12709 }
12710
12711 MonoArray *
12712 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12713 {
12714         MonoError error;
12715         MonoReflectionModuleBuilder *module = sig->module;
12716         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12717         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12718         guint32 buflen, i;
12719         MonoArray *result;
12720         SigBuffer buf;
12721
12722         check_array_for_usertypes (sig->arguments, &error);
12723         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12724
12725         sigbuffer_init (&buf, 32);
12726
12727         sigbuffer_add_value (&buf, 0x07);
12728         sigbuffer_add_value (&buf, na);
12729         if (assembly != NULL){
12730                 for (i = 0; i < na; ++i) {
12731                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12732                         encode_reflection_type (assembly, type, &buf);
12733                 }
12734         }
12735
12736         buflen = buf.p - buf.buf;
12737         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12738         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12739         sigbuffer_free (&buf);
12740
12741         return result;
12742 }
12743
12744 MonoArray *
12745 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12746 {
12747         MonoError error;
12748         MonoDynamicImage *assembly = sig->module->dynamic_image;
12749         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12750         guint32 buflen, i;
12751         MonoArray *result;
12752         SigBuffer buf;
12753
12754         check_array_for_usertypes (sig->arguments, &error);
12755         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12756
12757         sigbuffer_init (&buf, 32);
12758
12759         sigbuffer_add_value (&buf, 0x06);
12760         for (i = 0; i < na; ++i) {
12761                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12762                 encode_reflection_type (assembly, type, &buf);
12763         }
12764
12765         buflen = buf.p - buf.buf;
12766         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12767         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12768         sigbuffer_free (&buf);
12769
12770         return result;
12771 }
12772
12773 typedef struct {
12774         MonoMethod *handle;
12775         MonoDomain *domain;
12776 } DynamicMethodReleaseData;
12777
12778 /*
12779  * The runtime automatically clean up those after finalization.
12780 */      
12781 static MonoReferenceQueue *dynamic_method_queue;
12782
12783 static void
12784 free_dynamic_method (void *dynamic_method)
12785 {
12786         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12787         MonoDomain *domain = data->domain;
12788         MonoMethod *method = data->handle;
12789         guint32 dis_link;
12790
12791         mono_domain_lock (domain);
12792         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12793         g_hash_table_remove (domain->method_to_dyn_method, method);
12794         mono_domain_unlock (domain);
12795         g_assert (dis_link);
12796         mono_gchandle_free (dis_link);
12797
12798         mono_runtime_free_method (domain, method);
12799         g_free (data);
12800 }
12801
12802 void 
12803 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12804 {
12805         MonoReferenceQueue *queue;
12806         MonoMethod *handle;
12807         DynamicMethodReleaseData *release_data;
12808         ReflectionMethodBuilder rmb;
12809         MonoMethodSignature *sig;
12810         MonoClass *klass;
12811         MonoDomain *domain;
12812         GSList *l;
12813         int i;
12814
12815         if (mono_runtime_is_shutting_down ())
12816                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12817
12818         if (!(queue = dynamic_method_queue)) {
12819                 mono_loader_lock ();
12820                 if (!(queue = dynamic_method_queue))
12821                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12822                 mono_loader_unlock ();
12823         }
12824
12825         sig = dynamic_method_to_signature (mb);
12826
12827         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12828
12829         /*
12830          * Resolve references.
12831          */
12832         /* 
12833          * Every second entry in the refs array is reserved for storing handle_class,
12834          * which is needed by the ldtoken implementation in the JIT.
12835          */
12836         rmb.nrefs = mb->nrefs;
12837         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12838         for (i = 0; i < mb->nrefs; i += 2) {
12839                 MonoClass *handle_class;
12840                 gpointer ref;
12841                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12842
12843                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12844                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12845                         /*
12846                          * The referenced DynamicMethod should already be created by the managed
12847                          * code, except in the case of circular references. In that case, we store
12848                          * method in the refs array, and fix it up later when the referenced 
12849                          * DynamicMethod is created.
12850                          */
12851                         if (method->mhandle) {
12852                                 ref = method->mhandle;
12853                         } else {
12854                                 /* FIXME: GC object stored in unmanaged memory */
12855                                 ref = method;
12856
12857                                 /* FIXME: GC object stored in unmanaged memory */
12858                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12859                         }
12860                         handle_class = mono_defaults.methodhandle_class;
12861                 } else {
12862                         MonoException *ex = NULL;
12863                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12864                         if (!ref)
12865                                 ex = mono_get_exception_type_load (NULL, NULL);
12866                         else if (mono_security_core_clr_enabled ())
12867                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12868
12869                         if (ex) {
12870                                 g_free (rmb.refs);
12871                                 mono_raise_exception (ex);
12872                                 return;
12873                         }
12874                 }
12875
12876                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12877                 rmb.refs [i + 1] = handle_class;
12878         }               
12879
12880         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12881
12882         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12883         release_data = g_new (DynamicMethodReleaseData, 1);
12884         release_data->handle = handle;
12885         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12886         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12887                 g_free (release_data);
12888
12889         /* Fix up refs entries pointing at us */
12890         for (l = mb->referenced_by; l; l = l->next) {
12891                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12892                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12893                 gpointer *data;
12894                 
12895                 g_assert (method->mhandle);
12896
12897                 data = (gpointer*)wrapper->method_data;
12898                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12899                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12900                                 data [i + 1] = mb->mhandle;
12901                 }
12902         }
12903         g_slist_free (mb->referenced_by);
12904
12905         g_free (rmb.refs);
12906
12907         /* ilgen is no longer needed */
12908         mb->ilgen = NULL;
12909
12910         domain = mono_domain_get ();
12911         mono_domain_lock (domain);
12912         if (!domain->method_to_dyn_method)
12913                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12914         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12915         mono_domain_unlock (domain);
12916 }
12917
12918 #endif /* DISABLE_REFLECTION_EMIT */
12919
12920 /**
12921  * 
12922  * mono_reflection_is_valid_dynamic_token:
12923  * 
12924  * Returns TRUE if token is valid.
12925  * 
12926  */
12927 gboolean
12928 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12929 {
12930         return lookup_dyn_token (image, token) != NULL;
12931 }
12932
12933 MonoMethodSignature *
12934 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12935 {
12936         MonoMethodSignature *sig;
12937         g_assert (image_is_dynamic (image));
12938
12939         mono_error_init (error);
12940
12941         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12942         if (sig)
12943                 return sig;
12944
12945         return mono_method_signature_checked (method, error);
12946 }
12947
12948 #ifndef DISABLE_REFLECTION_EMIT
12949
12950 /**
12951  * mono_reflection_lookup_dynamic_token:
12952  *
12953  * Finish the Builder object pointed to by TOKEN and return the corresponding
12954  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12955  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12956  * mapping table.
12957  *
12958  * LOCKING: Take the loader lock
12959  */
12960 gpointer
12961 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12962 {
12963         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12964         MonoObject *obj;
12965         MonoClass *klass;
12966
12967         obj = lookup_dyn_token (assembly, token);
12968         if (!obj) {
12969                 if (valid_token)
12970                         g_error ("Could not find required dynamic token 0x%08x", token);
12971                 else
12972                         return NULL;
12973         }
12974
12975         if (!handle_class)
12976                 handle_class = &klass;
12977         return resolve_object (image, obj, handle_class, context);
12978 }
12979
12980 /*
12981  * ensure_complete_type:
12982  *
12983  *   Ensure that KLASS is completed if it is a dynamic type, or references
12984  * dynamic types.
12985  */
12986 static void
12987 ensure_complete_type (MonoClass *klass)
12988 {
12989         MonoError error;
12990
12991         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12992                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12993
12994                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12995                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12996
12997                 // Asserting here could break a lot of code
12998                 //g_assert (klass->wastypebuilder);
12999         }
13000
13001         if (klass->generic_class) {
13002                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13003                 int i;
13004
13005                 for (i = 0; i < inst->type_argc; ++i) {
13006                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13007                 }
13008         }
13009 }
13010
13011 static gpointer
13012 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13013 {
13014         MonoError error;
13015         gpointer result = NULL;
13016
13017         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13018                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13019                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13020                 *handle_class = mono_defaults.string_class;
13021                 g_assert (result);
13022         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13023                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13024                 MonoClass *mc = mono_class_from_mono_type (type);
13025                 if (!mono_class_init (mc))
13026                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13027
13028                 if (context) {
13029                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
13030                         result = mono_class_from_mono_type (inflated);
13031                         mono_metadata_free_type (inflated);
13032                 } else {
13033                         result = mono_class_from_mono_type (type);
13034                 }
13035                 *handle_class = mono_defaults.typehandle_class;
13036                 g_assert (result);
13037         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13038                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13039                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13040                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13041                 result = ((MonoReflectionMethod*)obj)->method;
13042                 if (context) {
13043                         MonoError error;
13044                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13045                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13046                 }
13047                 *handle_class = mono_defaults.methodhandle_class;
13048                 g_assert (result);
13049         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13050                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13051                 result = mb->mhandle;
13052                 if (!result) {
13053                         /* Type is not yet created */
13054                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13055
13056                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13057                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13058
13059                         /*
13060                          * Hopefully this has been filled in by calling CreateType() on the
13061                          * TypeBuilder.
13062                          */
13063                         /*
13064                          * TODO: This won't work if the application finishes another 
13065                          * TypeBuilder instance instead of this one.
13066                          */
13067                         result = mb->mhandle;
13068                 }
13069                 if (context) {
13070                         MonoError error;
13071                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13072                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13073                 }
13074                 *handle_class = mono_defaults.methodhandle_class;
13075         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13076                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13077
13078                 result = cb->mhandle;
13079                 if (!result) {
13080                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13081
13082                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13083                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13084                         result = cb->mhandle;
13085                 }
13086                 if (context) {
13087                         MonoError error;
13088                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13089                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13090                 }
13091                 *handle_class = mono_defaults.methodhandle_class;
13092         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13093                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13094
13095                 ensure_complete_type (field->parent);
13096                 if (context) {
13097                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
13098                         MonoClass *klass = mono_class_from_mono_type (inflated);
13099                         MonoClassField *inflated_field;
13100                         gpointer iter = NULL;
13101                         mono_metadata_free_type (inflated);
13102                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13103                                 if (!strcmp (field->name, inflated_field->name))
13104                                         break;
13105                         }
13106                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13107                         result = inflated_field;
13108                 } else {
13109                         result = field;
13110                 }
13111                 *handle_class = mono_defaults.fieldhandle_class;
13112                 g_assert (result);
13113         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13114                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13115                 result = fb->handle;
13116
13117                 if (!result) {
13118                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13119
13120                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13121                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13122                         result = fb->handle;
13123                 }
13124
13125                 if (fb->handle && fb->handle->parent->generic_container) {
13126                         MonoClass *klass = fb->handle->parent;
13127                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
13128                         MonoClass *inflated = mono_class_from_mono_type (type);
13129
13130                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13131                         g_assert (result);
13132                         mono_metadata_free_type (type);
13133                 }
13134                 *handle_class = mono_defaults.fieldhandle_class;
13135         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13136                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13137                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
13138                 MonoClass *klass;
13139
13140                 klass = type->data.klass;
13141                 if (klass->wastypebuilder) {
13142                         /* Already created */
13143                         result = klass;
13144                 }
13145                 else {
13146                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13147                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13148                         result = type->data.klass;
13149                         g_assert (result);
13150                 }
13151                 *handle_class = mono_defaults.typehandle_class;
13152         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13153                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13154                 MonoMethodSignature *sig;
13155                 int nargs, i;
13156
13157                 if (helper->arguments)
13158                         nargs = mono_array_length (helper->arguments);
13159                 else
13160                         nargs = 0;
13161
13162                 sig = mono_metadata_signature_alloc (image, nargs);
13163                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13164                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13165
13166                 if (helper->unmanaged_call_conv) { /* unmanaged */
13167                         sig->call_convention = helper->unmanaged_call_conv - 1;
13168                         sig->pinvoke = TRUE;
13169                 } else if (helper->call_conv & 0x02) {
13170                         sig->call_convention = MONO_CALL_VARARG;
13171                 } else {
13172                         sig->call_convention = MONO_CALL_DEFAULT;
13173                 }
13174
13175                 sig->param_count = nargs;
13176                 /* TODO: Copy type ? */
13177                 sig->ret = helper->return_type->type;
13178                 for (i = 0; i < nargs; ++i)
13179                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13180
13181                 result = sig;
13182                 *handle_class = NULL;
13183         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13184                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13185                 /* Already created by the managed code */
13186                 g_assert (method->mhandle);
13187                 result = method->mhandle;
13188                 *handle_class = mono_defaults.methodhandle_class;
13189         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13190                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13191                 type = mono_class_inflate_generic_type (type, context);
13192                 result = mono_class_from_mono_type (type);
13193                 *handle_class = mono_defaults.typehandle_class;
13194                 g_assert (result);
13195                 mono_metadata_free_type (type);
13196         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13197                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13198                 type = mono_class_inflate_generic_type (type, context);
13199                 result = mono_class_from_mono_type (type);
13200                 *handle_class = mono_defaults.typehandle_class;
13201                 g_assert (result);
13202                 mono_metadata_free_type (type);
13203         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13204                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13205                 MonoClass *inflated;
13206                 MonoType *type;
13207                 MonoClassField *field;
13208
13209                 if (is_sre_field_builder (mono_object_class (f->fb)))
13210                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13211                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13212                         field = ((MonoReflectionField*)f->fb)->field;
13213                 else
13214                         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)));
13215
13216                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13217                 inflated = mono_class_from_mono_type (type);
13218
13219                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13220                 ensure_complete_type (field->parent);
13221                 g_assert (result);
13222                 mono_metadata_free_type (type);
13223                 *handle_class = mono_defaults.fieldhandle_class;
13224         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13225                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13226                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13227                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13228                 MonoMethod *method;
13229
13230                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13231                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13232                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13233                         method = ((MonoReflectionMethod *)c->cb)->method;
13234                 else
13235                         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)));
13236
13237                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13238                 *handle_class = mono_defaults.methodhandle_class;
13239                 mono_metadata_free_type (type);
13240         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13241                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13242                 if (m->method_args) {
13243                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13244                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13245                         if (context) {
13246                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13247                                 mono_error_assert_ok (&error);
13248                         }
13249                 } else {
13250                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13251                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13252                         MonoMethod *method;
13253
13254                         if (is_sre_method_builder (mono_object_class (m->mb)))
13255                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13256                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13257                                 method = ((MonoReflectionMethod *)m->mb)->method;
13258                         else
13259                                 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)));
13260
13261                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13262                         mono_metadata_free_type (type);
13263                 }
13264                 *handle_class = mono_defaults.methodhandle_class;
13265         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13266                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13267                 MonoType *mtype;
13268                 MonoClass *klass;
13269                 MonoMethod *method;
13270                 gpointer iter;
13271                 char *name;
13272
13273                 mtype = mono_reflection_type_get_handle (m->parent);
13274                 klass = mono_class_from_mono_type (mtype);
13275
13276                 /* Find the method */
13277
13278                 name = mono_string_to_utf8 (m->name);
13279                 iter = NULL;
13280                 while ((method = mono_class_get_methods (klass, &iter))) {
13281                         if (!strcmp (method->name, name))
13282                                 break;
13283                 }
13284                 g_free (name);
13285
13286                 // FIXME:
13287                 g_assert (method);
13288                 // FIXME: Check parameters/return value etc. match
13289
13290                 result = method;
13291                 *handle_class = mono_defaults.methodhandle_class;
13292         } else if (is_sre_array (mono_object_get_class(obj)) ||
13293                                 is_sre_byref (mono_object_get_class(obj)) ||
13294                                 is_sre_pointer (mono_object_get_class(obj))) {
13295                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13296                 MonoType *type = mono_reflection_type_get_handle (ref_type);
13297
13298                 if (context) {
13299                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
13300                         result = mono_class_from_mono_type (inflated);
13301                         mono_metadata_free_type (inflated);
13302                 } else {
13303                         result = mono_class_from_mono_type (type);
13304                 }
13305                 *handle_class = mono_defaults.typehandle_class;
13306         } else {
13307                 g_print ("%s\n", obj->vtable->klass->name);
13308                 g_assert_not_reached ();
13309         }
13310         return result;
13311 }
13312
13313 #else /* DISABLE_REFLECTION_EMIT */
13314
13315 MonoArray*
13316 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13317 {
13318         g_assert_not_reached ();
13319         return NULL;
13320 }
13321
13322 void
13323 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13324 {
13325         g_assert_not_reached ();
13326 }
13327
13328 void
13329 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13330 {
13331         g_assert_not_reached ();
13332 }
13333
13334 void
13335 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13336 {
13337         g_assert_not_reached ();
13338 }
13339
13340 void
13341 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13342 {
13343         g_assert_not_reached ();
13344 }
13345
13346 void
13347 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13348 {
13349         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13350 }
13351
13352 void
13353 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13354 {
13355         g_assert_not_reached ();
13356 }
13357
13358 void
13359 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13360 {
13361         g_assert_not_reached ();
13362 }
13363
13364 MonoReflectionModule *
13365 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13366 {
13367         g_assert_not_reached ();
13368         return NULL;
13369 }
13370
13371 guint32
13372 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13373 {
13374         g_assert_not_reached ();
13375         return 0;
13376 }
13377
13378 guint32
13379 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13380 {
13381         g_assert_not_reached ();
13382         return 0;
13383 }
13384
13385 guint32
13386 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13387                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13388 {
13389         g_assert_not_reached ();
13390         return 0;
13391 }
13392
13393 void
13394 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13395 {
13396 }
13397
13398 void
13399 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13400 {
13401         g_assert_not_reached ();
13402 }
13403
13404 void
13405 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13406 {
13407         *overrides = NULL;
13408         *num_overrides = 0;
13409 }
13410
13411 MonoReflectionEvent *
13412 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13413 {
13414         g_assert_not_reached ();
13415         return NULL;
13416 }
13417
13418 MonoReflectionType*
13419 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13420 {
13421         g_assert_not_reached ();
13422         return NULL;
13423 }
13424
13425 void
13426 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13427 {
13428         g_assert_not_reached ();
13429 }
13430
13431 MonoArray *
13432 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13433 {
13434         g_assert_not_reached ();
13435         return NULL;
13436 }
13437
13438 MonoArray *
13439 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13440 {
13441         g_assert_not_reached ();
13442         return NULL;
13443 }
13444
13445 void 
13446 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13447 {
13448 }
13449
13450 gpointer
13451 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13452 {
13453         return NULL;
13454 }
13455
13456 MonoType*
13457 mono_reflection_type_get_handle (MonoReflectionType* ref)
13458 {
13459         if (!ref)
13460                 return NULL;
13461         return ref->type;
13462 }
13463
13464 void
13465 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13466 {
13467         g_assert_not_reached ();
13468 }
13469
13470 #endif /* DISABLE_REFLECTION_EMIT */
13471
13472 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13473 const static guint32 declsec_flags_map[] = {
13474         0x00000000,                                     /* empty */
13475         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13476         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13477         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13478         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13479         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13480         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13481         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13482         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13483         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13484         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13485         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13486         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13487         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13488         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13489         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13490         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13491         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13492         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13493 };
13494
13495 /*
13496  * Returns flags that includes all available security action associated to the handle.
13497  * @token: metadata token (either for a class or a method)
13498  * @image: image where resides the metadata.
13499  */
13500 static guint32
13501 mono_declsec_get_flags (MonoImage *image, guint32 token)
13502 {
13503         int index = mono_metadata_declsec_from_index (image, token);
13504         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13505         guint32 result = 0;
13506         guint32 action;
13507         int i;
13508
13509         /* HasSecurity can be present for other, not specially encoded, attributes,
13510            e.g. SuppressUnmanagedCodeSecurityAttribute */
13511         if (index < 0)
13512                 return 0;
13513
13514         for (i = index; i < t->rows; i++) {
13515                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13516
13517                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13518                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13519                         break;
13520
13521                 action = cols [MONO_DECL_SECURITY_ACTION];
13522                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13523                         result |= declsec_flags_map [action];
13524                 } else {
13525                         g_assert_not_reached ();
13526                 }
13527         }
13528         return result;
13529 }
13530
13531 /*
13532  * Get the security actions (in the form of flags) associated with the specified method.
13533  *
13534  * @method: The method for which we want the declarative security flags.
13535  * Return the declarative security flags for the method (only).
13536  *
13537  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13538  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13539  */
13540 guint32
13541 mono_declsec_flags_from_method (MonoMethod *method)
13542 {
13543         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13544                 /* FIXME: No cache (for the moment) */
13545                 guint32 idx = mono_method_get_index (method);
13546                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13547                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13548                 return mono_declsec_get_flags (method->klass->image, idx);
13549         }
13550         return 0;
13551 }
13552
13553 /*
13554  * Get the security actions (in the form of flags) associated with the specified class.
13555  *
13556  * @klass: The class for which we want the declarative security flags.
13557  * Return the declarative security flags for the class.
13558  *
13559  * Note: We cache the flags inside the MonoClass structure as this will get 
13560  *       called very often (at least for each method).
13561  */
13562 guint32
13563 mono_declsec_flags_from_class (MonoClass *klass)
13564 {
13565         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13566                 if (!klass->ext || !klass->ext->declsec_flags) {
13567                         guint32 idx;
13568
13569                         idx = mono_metadata_token_index (klass->type_token);
13570                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13571                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13572                         mono_loader_lock ();
13573                         mono_class_alloc_ext (klass);
13574                         mono_loader_unlock ();
13575                         /* we cache the flags on classes */
13576                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13577                 }
13578                 return klass->ext->declsec_flags;
13579         }
13580         return 0;
13581 }
13582
13583 /*
13584  * Get the security actions (in the form of flags) associated with the specified assembly.
13585  *
13586  * @assembly: The assembly for which we want the declarative security flags.
13587  * Return the declarative security flags for the assembly.
13588  */
13589 guint32
13590 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13591 {
13592         guint32 idx = 1; /* there is only one assembly */
13593         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13594         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13595         return mono_declsec_get_flags (assembly->image, idx);
13596 }
13597
13598
13599 /*
13600  * Fill actions for the specific index (which may either be an encoded class token or
13601  * an encoded method token) from the metadata image.
13602  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13603  */
13604 static MonoBoolean
13605 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13606         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13607 {
13608         MonoBoolean result = FALSE;
13609         MonoTableInfo *t;
13610         guint32 cols [MONO_DECL_SECURITY_SIZE];
13611         int index = mono_metadata_declsec_from_index (image, token);
13612         int i;
13613
13614         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13615         for (i = index; i < t->rows; i++) {
13616                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13617
13618                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13619                         return result;
13620
13621                 /* if present only replace (class) permissions with method permissions */
13622                 /* if empty accept either class or method permissions */
13623                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13624                         if (!actions->demand.blob) {
13625                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13626                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13627                                 actions->demand.blob = (char*) (blob + 2);
13628                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13629                                 result = TRUE;
13630                         }
13631                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13632                         if (!actions->noncasdemand.blob) {
13633                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13634                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13635                                 actions->noncasdemand.blob = (char*) (blob + 2);
13636                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13637                                 result = TRUE;
13638                         }
13639                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13640                         if (!actions->demandchoice.blob) {
13641                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13642                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13643                                 actions->demandchoice.blob = (char*) (blob + 2);
13644                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13645                                 result = TRUE;
13646                         }
13647                 }
13648         }
13649
13650         return result;
13651 }
13652
13653 static MonoBoolean
13654 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13655         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13656 {
13657         guint32 idx = mono_metadata_token_index (klass->type_token);
13658         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13659         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13660         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13661 }
13662
13663 static MonoBoolean
13664 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13665         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13666 {
13667         guint32 idx = mono_method_get_index (method);
13668         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13669         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13670         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13671 }
13672
13673 /*
13674  * Collect all actions (that requires to generate code in mini) assigned for
13675  * the specified method.
13676  * Note: Don't use the content of actions if the function return FALSE.
13677  */
13678 MonoBoolean
13679 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13680 {
13681         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13682                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13683         MonoBoolean result = FALSE;
13684         guint32 flags;
13685
13686         /* quick exit if no declarative security is present in the metadata */
13687         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13688                 return FALSE;
13689
13690         /* we want the original as the wrapper is "free" of the security informations */
13691         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13692                 method = mono_marshal_method_from_wrapper (method);
13693                 if (!method)
13694                         return FALSE;
13695         }
13696
13697         /* First we look for method-level attributes */
13698         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13699                 mono_class_init (method->klass);
13700                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13701
13702                 result = mono_declsec_get_method_demands_params (method, demands, 
13703                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13704         }
13705
13706         /* Here we use (or create) the class declarative cache to look for demands */
13707         flags = mono_declsec_flags_from_class (method->klass);
13708         if (flags & mask) {
13709                 if (!result) {
13710                         mono_class_init (method->klass);
13711                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13712                 }
13713                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13714                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13715         }
13716
13717         /* The boolean return value is used as a shortcut in case nothing needs to
13718            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13719         return result;
13720 }
13721
13722
13723 /*
13724  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13725  *
13726  * Note: Don't use the content of actions if the function return FALSE.
13727  */
13728 MonoBoolean
13729 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13730 {
13731         MonoBoolean result = FALSE;
13732         guint32 flags;
13733
13734         /* quick exit if no declarative security is present in the metadata */
13735         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13736                 return FALSE;
13737
13738         /* we want the original as the wrapper is "free" of the security informations */
13739         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13740                 method = mono_marshal_method_from_wrapper (method);
13741                 if (!method)
13742                         return FALSE;
13743         }
13744
13745         /* results are independant - zeroize both */
13746         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13747         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13748
13749         /* First we look for method-level attributes */
13750         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13751                 mono_class_init (method->klass);
13752
13753                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13754                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13755         }
13756
13757         /* Here we use (or create) the class declarative cache to look for demands */
13758         flags = mono_declsec_flags_from_class (method->klass);
13759         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13760                 mono_class_init (method->klass);
13761
13762                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13763                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13764         }
13765
13766         return result;
13767 }
13768
13769 /*
13770  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13771  *
13772  * @klass       The inherited class - this is the class that provides the security check (attributes)
13773  * @demans      
13774  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13775  * 
13776  * Note: Don't use the content of actions if the function return FALSE.
13777  */
13778 MonoBoolean
13779 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13780 {
13781         MonoBoolean result = FALSE;
13782         guint32 flags;
13783
13784         /* quick exit if no declarative security is present in the metadata */
13785         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13786                 return FALSE;
13787
13788         /* Here we use (or create) the class declarative cache to look for demands */
13789         flags = mono_declsec_flags_from_class (klass);
13790         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13791                 mono_class_init (klass);
13792                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13793
13794                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13795                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13796         }
13797
13798         return result;
13799 }
13800
13801 /*
13802  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13803  *
13804  * Note: Don't use the content of actions if the function return FALSE.
13805  */
13806 MonoBoolean
13807 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13808 {
13809         /* quick exit if no declarative security is present in the metadata */
13810         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13811                 return FALSE;
13812
13813         /* we want the original as the wrapper is "free" of the security informations */
13814         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13815                 method = mono_marshal_method_from_wrapper (method);
13816                 if (!method)
13817                         return FALSE;
13818         }
13819
13820         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13821                 mono_class_init (method->klass);
13822                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13823
13824                 return mono_declsec_get_method_demands_params (method, demands, 
13825                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13826         }
13827         return FALSE;
13828 }
13829
13830
13831 static MonoBoolean
13832 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13833 {
13834         guint32 cols [MONO_DECL_SECURITY_SIZE];
13835         MonoTableInfo *t;
13836         int i;
13837
13838         int index = mono_metadata_declsec_from_index (image, token);
13839         if (index == -1)
13840                 return FALSE;
13841
13842         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13843         for (i = index; i < t->rows; i++) {
13844                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13845
13846                 /* shortcut - index are ordered */
13847                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13848                         return FALSE;
13849
13850                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13851                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13852                         entry->blob = (char*) (metadata + 2);
13853                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13854                         return TRUE;
13855                 }
13856         }
13857
13858         return FALSE;
13859 }
13860
13861 MonoBoolean
13862 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13863 {
13864         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13865                 guint32 idx = mono_method_get_index (method);
13866                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13867                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13868                 return get_declsec_action (method->klass->image, idx, action, entry);
13869         }
13870         return FALSE;
13871 }
13872
13873 MonoBoolean
13874 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13875 {
13876         /* use cache */
13877         guint32 flags = mono_declsec_flags_from_class (klass);
13878         if (declsec_flags_map [action] & flags) {
13879                 guint32 idx = mono_metadata_token_index (klass->type_token);
13880                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13881                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13882                 return get_declsec_action (klass->image, idx, action, entry);
13883         }
13884         return FALSE;
13885 }
13886
13887 MonoBoolean
13888 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13889 {
13890         guint32 idx = 1; /* there is only one assembly */
13891         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13892         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13893
13894         return get_declsec_action (assembly->image, idx, action, entry);
13895 }
13896
13897 gboolean
13898 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13899 {
13900         MonoError error;
13901         MonoObject *res, *exc;
13902         void *params [1];
13903         static MonoMethod *method = NULL;
13904
13905         if (method == NULL) {
13906                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13907                 g_assert (method);
13908         }
13909
13910         /* 
13911          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13912          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13913          */
13914         g_assert (mono_class_get_ref_info (klass));
13915         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13916
13917         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13918         mono_error_raise_exception (&error); /* FIXME don't raise here */
13919
13920         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13921
13922         if (exc || !mono_error_ok (&error)) {
13923                 mono_error_cleanup (&error);
13924                 return FALSE;
13925         } else
13926                 return *(MonoBoolean*)mono_object_unbox (res);
13927 }
13928
13929 /**
13930  * mono_reflection_type_get_type:
13931  * @reftype: the System.Type object
13932  *
13933  * Returns the MonoType* associated with the C# System.Type object @reftype.
13934  */
13935 MonoType*
13936 mono_reflection_type_get_type (MonoReflectionType *reftype)
13937 {
13938         g_assert (reftype);
13939
13940         return mono_reflection_type_get_handle (reftype);
13941 }
13942
13943 /**
13944  * mono_reflection_assembly_get_assembly:
13945  * @refassembly: the System.Reflection.Assembly object
13946  *
13947  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13948  */
13949 MonoAssembly*
13950 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13951 {
13952         g_assert (refassembly);
13953
13954         return refassembly->assembly;
13955 }
13956