b40ce1bf90ecc9853074ad36b3778b99217dda83
[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, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
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, MonoError *error);
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, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static gboolean type_is_reference (MonoType *type);
191
192 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
193 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
194 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
195
196 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
197 static void init_type_builder_generics (MonoObject *type);
198
199 #define RESOLVE_TYPE(type, error) do {                                  \
200         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
201 } while (0)
202 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
203         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
204         __type = mono_reflection_type_resolve_user_types (__type, error); \
205         if (mono_error_ok (error))                                      \
206                 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 } while (0)
208
209 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
210
211 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
212 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
213
214 #if SIZEOF_VOID_P == 4
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
216 #else
217 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #endif
219
220 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
221 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
222
223 /* Class lazy loading functions */
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
234 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
235 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
236 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
237 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
238 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
241 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
242 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
243
244 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
245 static GPtrArray *dynamic_images;
246 static mono_mutex_t dynamic_images_mutex;
247
248 static inline void
249 dynamic_images_lock (void)
250 {
251         mono_os_mutex_lock (&dynamic_images_mutex);
252 }
253
254 static inline void
255 dynamic_images_unlock (void)
256 {
257         mono_os_mutex_unlock (&dynamic_images_mutex);
258 }
259
260 /**
261  * mono_find_dynamic_image_owner:
262  *
263  * Find the dynamic image, if any, which a given pointer is located in the memory of.
264  */
265 MonoImage *
266 mono_find_dynamic_image_owner (void *ptr)
267 {
268         MonoImage *owner = NULL;
269         int i;
270
271         dynamic_images_lock ();
272
273         if (dynamic_images)
274         {
275                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
276                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
277                         if (mono_mempool_contains_addr (image->mempool, ptr))
278                                 owner = image;
279                 }
280         }
281
282         dynamic_images_unlock ();
283
284         return owner;
285 }
286
287 void
288 mono_reflection_init (void)
289 {
290         mono_os_mutex_init (&dynamic_images_mutex);
291 }
292
293 static inline void
294 dynamic_image_lock (MonoDynamicImage *image)
295 {
296         MONO_PREPARE_BLOCKING;
297         mono_image_lock ((MonoImage*)image);
298         MONO_FINISH_BLOCKING;
299 }
300
301 static inline void
302 dynamic_image_unlock (MonoDynamicImage *image)
303 {
304         mono_image_unlock ((MonoImage*)image);
305 }
306
307 static void
308 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
309 {
310         MONO_REQ_GC_UNSAFE_MODE;
311
312         dynamic_image_lock (assembly);
313         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
314         dynamic_image_unlock (assembly);
315 }
316
317 static MonoObject*
318 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
319 {
320         MONO_REQ_GC_UNSAFE_MODE;
321
322         MonoObject *obj;
323
324         dynamic_image_lock (assembly);
325         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
326         dynamic_image_unlock (assembly);
327
328         return obj;
329 }
330
331 static void
332 sigbuffer_init (SigBuffer *buf, int size)
333 {
334         MONO_REQ_GC_NEUTRAL_MODE;
335
336         buf->buf = (char *)g_malloc (size);
337         buf->p = buf->buf;
338         buf->end = buf->buf + size;
339 }
340
341 static void
342 sigbuffer_make_room (SigBuffer *buf, int size)
343 {
344         MONO_REQ_GC_NEUTRAL_MODE;
345
346         if (buf->end - buf->p < size) {
347                 int new_size = buf->end - buf->buf + size + 32;
348                 char *p = (char *)g_realloc (buf->buf, new_size);
349                 size = buf->p - buf->buf;
350                 buf->buf = p;
351                 buf->p = p + size;
352                 buf->end = buf->buf + new_size;
353         }
354 }
355
356 static void
357 sigbuffer_add_value (SigBuffer *buf, guint32 val)
358 {
359         MONO_REQ_GC_NEUTRAL_MODE;
360
361         sigbuffer_make_room (buf, 6);
362         mono_metadata_encode_value (val, buf->p, &buf->p);
363 }
364
365 static void
366 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
367 {
368         MONO_REQ_GC_NEUTRAL_MODE;
369
370         sigbuffer_make_room (buf, 1);
371         buf->p [0] = val;
372         buf->p++;
373 }
374
375 static void
376 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
377 {
378         MONO_REQ_GC_NEUTRAL_MODE;
379
380         sigbuffer_make_room (buf, size);
381         memcpy (buf->p, p, size);
382         buf->p += size;
383 }
384
385 static void
386 sigbuffer_free (SigBuffer *buf)
387 {
388         MONO_REQ_GC_NEUTRAL_MODE;
389
390         g_free (buf->buf);
391 }
392
393 #ifndef DISABLE_REFLECTION_EMIT
394 /**
395  * mp_g_alloc:
396  *
397  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
398  * from the C heap.
399  */
400 static gpointer
401 image_g_malloc (MonoImage *image, guint size)
402 {
403         MONO_REQ_GC_NEUTRAL_MODE;
404
405         if (image)
406                 return mono_image_alloc (image, size);
407         else
408                 return g_malloc (size);
409 }
410 #endif /* !DISABLE_REFLECTION_EMIT */
411
412 /**
413  * image_g_alloc0:
414  *
415  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
416  * from the C heap.
417  */
418 static gpointer
419 image_g_malloc0 (MonoImage *image, guint size)
420 {
421         MONO_REQ_GC_NEUTRAL_MODE;
422
423         if (image)
424                 return mono_image_alloc0 (image, size);
425         else
426                 return g_malloc0 (size);
427 }
428
429 /**
430  * image_g_free:
431  * @image: a MonoImage
432  * @ptr: pointer
433  *
434  * If @image is NULL, free @ptr, otherwise do nothing.
435  */
436 static void
437 image_g_free (MonoImage *image, gpointer ptr)
438 {
439         if (image == NULL)
440                 g_free (ptr);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static char*
445 image_strdup (MonoImage *image, const char *s)
446 {
447         MONO_REQ_GC_NEUTRAL_MODE;
448
449         if (image)
450                 return mono_image_strdup (image, s);
451         else
452                 return g_strdup (s);
453 }
454 #endif
455
456 #define image_g_new(image,struct_type, n_structs)               \
457     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
458
459 #define image_g_new0(image,struct_type, n_structs)              \
460     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
461
462
463 static void
464 alloc_table (MonoDynamicTable *table, guint nrows)
465 {
466         MONO_REQ_GC_NEUTRAL_MODE;
467
468         table->rows = nrows;
469         g_assert (table->columns);
470         if (nrows + 1 >= table->alloc_rows) {
471                 while (nrows + 1 >= table->alloc_rows) {
472                         if (table->alloc_rows == 0)
473                                 table->alloc_rows = 16;
474                         else
475                                 table->alloc_rows *= 2;
476                 }
477
478                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
479         }
480 }
481
482 static void
483 make_room_in_stream (MonoDynamicStream *stream, int size)
484 {
485         MONO_REQ_GC_NEUTRAL_MODE;
486
487         if (size <= stream->alloc_size)
488                 return;
489         
490         while (stream->alloc_size <= size) {
491                 if (stream->alloc_size < 4096)
492                         stream->alloc_size = 4096;
493                 else
494                         stream->alloc_size *= 2;
495         }
496         
497         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
498 }
499
500 static guint32
501 string_heap_insert (MonoDynamicStream *sh, const char *str)
502 {
503         MONO_REQ_GC_NEUTRAL_MODE;
504
505         guint32 idx;
506         guint32 len;
507         gpointer oldkey, oldval;
508
509         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
510                 return GPOINTER_TO_UINT (oldval);
511
512         len = strlen (str) + 1;
513         idx = sh->index;
514         
515         make_room_in_stream (sh, idx + len);
516
517         /*
518          * We strdup the string even if we already copy them in sh->data
519          * so that the string pointers in the hash remain valid even if
520          * we need to realloc sh->data. We may want to avoid that later.
521          */
522         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
523         memcpy (sh->data + idx, str, len);
524         sh->index += len;
525         return idx;
526 }
527
528 static guint32
529 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
530 {
531         MONO_REQ_GC_UNSAFE_MODE;
532
533         char *name = mono_string_to_utf8 (str);
534         guint32 idx;
535         idx = string_heap_insert (sh, name);
536         g_free (name);
537         return idx;
538 }
539
540 #ifndef DISABLE_REFLECTION_EMIT
541 static void
542 string_heap_init (MonoDynamicStream *sh)
543 {
544         MONO_REQ_GC_NEUTRAL_MODE;
545
546         sh->index = 0;
547         sh->alloc_size = 4096;
548         sh->data = (char *)g_malloc (4096);
549         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
550         string_heap_insert (sh, "");
551 }
552 #endif
553
554 static guint32
555 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
556 {
557         MONO_REQ_GC_NEUTRAL_MODE;
558
559         guint32 idx;
560         
561         make_room_in_stream (stream, stream->index + len);
562         memcpy (stream->data + stream->index, data, len);
563         idx = stream->index;
564         stream->index += len;
565         /* 
566          * align index? Not without adding an additional param that controls it since
567          * we may store a blob value in pieces.
568          */
569         return idx;
570 }
571
572 static guint32
573 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
574 {
575         MONO_REQ_GC_NEUTRAL_MODE;
576
577         guint32 idx;
578         
579         make_room_in_stream (stream, stream->index + len);
580         memset (stream->data + stream->index, 0, len);
581         idx = stream->index;
582         stream->index += len;
583         return idx;
584 }
585
586 static void
587 stream_data_align (MonoDynamicStream *stream)
588 {
589         MONO_REQ_GC_NEUTRAL_MODE;
590
591         char buf [4] = {0};
592         guint32 count = stream->index % 4;
593
594         /* we assume the stream data will be aligned */
595         if (count)
596                 mono_image_add_stream_data (stream, buf, 4 - count);
597 }
598
599 #ifndef DISABLE_REFLECTION_EMIT
600 static int
601 mono_blob_entry_hash (const char* str)
602 {
603         MONO_REQ_GC_NEUTRAL_MODE;
604
605         guint len, h;
606         const char *end;
607         len = mono_metadata_decode_blob_size (str, &str);
608         if (len > 0) {
609                 end = str + len;
610                 h = *str;
611                 for (str += 1; str < end; str++)
612                         h = (h << 5) - h + *str;
613                 return h;
614         } else {
615                 return 0;
616         }
617 }
618
619 static gboolean
620 mono_blob_entry_equal (const char *str1, const char *str2) {
621         MONO_REQ_GC_NEUTRAL_MODE;
622
623         int len, len2;
624         const char *end1;
625         const char *end2;
626         len = mono_metadata_decode_blob_size (str1, &end1);
627         len2 = mono_metadata_decode_blob_size (str2, &end2);
628         if (len != len2)
629                 return 0;
630         return memcmp (end1, end2, len) == 0;
631 }
632 #endif
633 static guint32
634 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
635 {
636         MONO_REQ_GC_NEUTRAL_MODE;
637
638         guint32 idx;
639         char *copy;
640         gpointer oldkey, oldval;
641
642         copy = (char *)g_malloc (s1+s2);
643         memcpy (copy, b1, s1);
644         memcpy (copy + s1, b2, s2);
645         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
646                 g_free (copy);
647                 idx = GPOINTER_TO_UINT (oldval);
648         } else {
649                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
650                 mono_image_add_stream_data (&assembly->blob, b2, s2);
651                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
652         }
653         return idx;
654 }
655
656 static guint32
657 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
658 {
659         MONO_REQ_GC_NEUTRAL_MODE;
660
661         char blob_size [8];
662         char *b = blob_size;
663         guint32 size = buf->p - buf->buf;
664         /* store length */
665         g_assert (size <= (buf->end - buf->buf));
666         mono_metadata_encode_value (size, b, &b);
667         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
668 }
669
670 /*
671  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
672  * dest may be misaligned.
673  */
674 static void
675 swap_with_size (char *dest, const char* val, int len, int nelem) {
676         MONO_REQ_GC_NEUTRAL_MODE;
677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
678         int elem;
679
680         for (elem = 0; elem < nelem; ++elem) {
681                 switch (len) {
682                 case 1:
683                         *dest = *val;
684                         break;
685                 case 2:
686                         dest [0] = val [1];
687                         dest [1] = val [0];
688                         break;
689                 case 4:
690                         dest [0] = val [3];
691                         dest [1] = val [2];
692                         dest [2] = val [1];
693                         dest [3] = val [0];
694                         break;
695                 case 8:
696                         dest [0] = val [7];
697                         dest [1] = val [6];
698                         dest [2] = val [5];
699                         dest [3] = val [4];
700                         dest [4] = val [3];
701                         dest [5] = val [2];
702                         dest [6] = val [1];
703                         dest [7] = val [0];
704                         break;
705                 default:
706                         g_assert_not_reached ();
707                 }
708                 dest += len;
709                 val += len;
710         }
711 #else
712         memcpy (dest, val, len * nelem);
713 #endif
714 }
715
716 static guint32
717 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
718 {
719         MONO_REQ_GC_UNSAFE_MODE;
720         
721         char blob_size [64];
722         char *b = blob_size;
723         guint32 idx = 0, len;
724
725         len = str->length * 2;
726         mono_metadata_encode_value (len, b, &b);
727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
728         {
729                 char *swapped = g_malloc (2 * mono_string_length (str));
730                 const char *p = (const char*)mono_string_chars (str);
731
732                 swap_with_size (swapped, p, 2, mono_string_length (str));
733                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
734                 g_free (swapped);
735         }
736 #else
737         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
738 #endif
739         return idx;
740 }
741
742 #ifndef DISABLE_REFLECTION_EMIT
743 static MonoClass *
744 default_class_from_mono_type (MonoType *type)
745 {
746         MONO_REQ_GC_NEUTRAL_MODE;
747
748         switch (type->type) {
749         case MONO_TYPE_OBJECT:
750                 return mono_defaults.object_class;
751         case MONO_TYPE_VOID:
752                 return mono_defaults.void_class;
753         case MONO_TYPE_BOOLEAN:
754                 return mono_defaults.boolean_class;
755         case MONO_TYPE_CHAR:
756                 return mono_defaults.char_class;
757         case MONO_TYPE_I1:
758                 return mono_defaults.sbyte_class;
759         case MONO_TYPE_U1:
760                 return mono_defaults.byte_class;
761         case MONO_TYPE_I2:
762                 return mono_defaults.int16_class;
763         case MONO_TYPE_U2:
764                 return mono_defaults.uint16_class;
765         case MONO_TYPE_I4:
766                 return mono_defaults.int32_class;
767         case MONO_TYPE_U4:
768                 return mono_defaults.uint32_class;
769         case MONO_TYPE_I:
770                 return mono_defaults.int_class;
771         case MONO_TYPE_U:
772                 return mono_defaults.uint_class;
773         case MONO_TYPE_I8:
774                 return mono_defaults.int64_class;
775         case MONO_TYPE_U8:
776                 return mono_defaults.uint64_class;
777         case MONO_TYPE_R4:
778                 return mono_defaults.single_class;
779         case MONO_TYPE_R8:
780                 return mono_defaults.double_class;
781         case MONO_TYPE_STRING:
782                 return mono_defaults.string_class;
783         default:
784                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
785                 g_assert_not_reached ();
786         }
787         
788         return NULL;
789 }
790 #endif
791
792 /*
793  * mono_class_get_ref_info:
794  *
795  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
796  */
797 gpointer
798 mono_class_get_ref_info (MonoClass *klass)
799 {
800         MONO_REQ_GC_UNSAFE_MODE;
801
802         if (klass->ref_info_handle == 0)
803                 return NULL;
804         else
805                 return mono_gchandle_get_target (klass->ref_info_handle);
806 }
807
808 void
809 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
810 {
811         MONO_REQ_GC_UNSAFE_MODE;
812
813         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
814         g_assert (klass->ref_info_handle != 0);
815 }
816
817 void
818 mono_class_free_ref_info (MonoClass *klass)
819 {
820         MONO_REQ_GC_NEUTRAL_MODE;
821
822         if (klass->ref_info_handle) {
823                 mono_gchandle_free (klass->ref_info_handle);
824                 klass->ref_info_handle = 0;
825         }
826 }
827
828 static void
829 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
830 {
831         MONO_REQ_GC_NEUTRAL_MODE;
832
833         int i;
834         MonoGenericInst *class_inst;
835         MonoClass *klass;
836
837         g_assert (gclass);
838
839         class_inst = gclass->context.class_inst;
840
841         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
842         klass = gclass->container_class;
843         sigbuffer_add_value (buf, klass->byval_arg.type);
844         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
845
846         sigbuffer_add_value (buf, class_inst->type_argc);
847         for (i = 0; i < class_inst->type_argc; ++i)
848                 encode_type (assembly, class_inst->type_argv [i], buf);
849
850 }
851
852 static void
853 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
854 {
855         MONO_REQ_GC_NEUTRAL_MODE;
856
857         if (!type) {
858                 g_assert_not_reached ();
859                 return;
860         }
861                 
862         if (type->byref)
863                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
864
865         switch (type->type){
866         case MONO_TYPE_VOID:
867         case MONO_TYPE_BOOLEAN:
868         case MONO_TYPE_CHAR:
869         case MONO_TYPE_I1:
870         case MONO_TYPE_U1:
871         case MONO_TYPE_I2:
872         case MONO_TYPE_U2:
873         case MONO_TYPE_I4:
874         case MONO_TYPE_U4:
875         case MONO_TYPE_I8:
876         case MONO_TYPE_U8:
877         case MONO_TYPE_R4:
878         case MONO_TYPE_R8:
879         case MONO_TYPE_I:
880         case MONO_TYPE_U:
881         case MONO_TYPE_STRING:
882         case MONO_TYPE_OBJECT:
883         case MONO_TYPE_TYPEDBYREF:
884                 sigbuffer_add_value (buf, type->type);
885                 break;
886         case MONO_TYPE_PTR:
887                 sigbuffer_add_value (buf, type->type);
888                 encode_type (assembly, type->data.type, buf);
889                 break;
890         case MONO_TYPE_SZARRAY:
891                 sigbuffer_add_value (buf, type->type);
892                 encode_type (assembly, &type->data.klass->byval_arg, buf);
893                 break;
894         case MONO_TYPE_VALUETYPE:
895         case MONO_TYPE_CLASS: {
896                 MonoClass *k = mono_class_from_mono_type (type);
897
898                 if (k->generic_container) {
899                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
900                         encode_generic_class (assembly, gclass, buf);
901                 } else {
902                         /*
903                          * Make sure we use the correct type.
904                          */
905                         sigbuffer_add_value (buf, k->byval_arg.type);
906                         /*
907                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
908                          * otherwise two typerefs could point to the same type, leading to
909                          * verification errors.
910                          */
911                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
912                 }
913                 break;
914         }
915         case MONO_TYPE_ARRAY:
916                 sigbuffer_add_value (buf, type->type);
917                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
918                 sigbuffer_add_value (buf, type->data.array->rank);
919                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
920                 sigbuffer_add_value (buf, 0);
921                 break;
922         case MONO_TYPE_GENERICINST:
923                 encode_generic_class (assembly, type->data.generic_class, buf);
924                 break;
925         case MONO_TYPE_VAR:
926         case MONO_TYPE_MVAR:
927                 sigbuffer_add_value (buf, type->type);
928                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
929                 break;
930         default:
931                 g_error ("need to encode type %x", type->type);
932         }
933 }
934
935 static void
936 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
937 {
938         MONO_REQ_GC_UNSAFE_MODE;
939
940         mono_error_init (error);
941
942         if (!type) {
943                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
944                 return;
945         }
946
947         MonoType *t = mono_reflection_type_get_handle (type, error);
948         return_if_nok (error);
949         encode_type (assembly, t, buf);
950 }
951
952 static void
953 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
954 {
955         MONO_REQ_GC_UNSAFE_MODE;
956
957         int i;
958
959         mono_error_init (error);
960
961         if (modreq) {
962                 for (i = 0; i < mono_array_length (modreq); ++i) {
963                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
964                         return_if_nok (error);
965                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
966                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
967                 }
968         }
969         if (modopt) {
970                 for (i = 0; i < mono_array_length (modopt); ++i) {
971                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
972                         return_if_nok (error);
973                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
974                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
975                 }
976         }
977 }
978
979 #ifndef DISABLE_REFLECTION_EMIT
980 static guint32
981 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
982 {
983         MONO_REQ_GC_UNSAFE_MODE;
984
985         SigBuffer buf;
986         int i;
987         guint32 nparams =  sig->param_count;
988         guint32 idx;
989
990         if (!assembly->save)
991                 return 0;
992
993         sigbuffer_init (&buf, 32);
994         /*
995          * FIXME: vararg, explicit_this, differenc call_conv values...
996          */
997         idx = sig->call_convention;
998         if (sig->hasthis)
999                 idx |= 0x20; /* hasthis */
1000         if (sig->generic_param_count)
1001                 idx |= 0x10; /* generic */
1002         sigbuffer_add_byte (&buf, idx);
1003         if (sig->generic_param_count)
1004                 sigbuffer_add_value (&buf, sig->generic_param_count);
1005         sigbuffer_add_value (&buf, nparams);
1006         encode_type (assembly, sig->ret, &buf);
1007         for (i = 0; i < nparams; ++i) {
1008                 if (i == sig->sentinelpos)
1009                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1010                 encode_type (assembly, sig->params [i], &buf);
1011         }
1012         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1013         sigbuffer_free (&buf);
1014         return idx;
1015 }
1016 #endif
1017
1018 static guint32
1019 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1020 {
1021         MONO_REQ_GC_UNSAFE_MODE;
1022
1023         mono_error_init (error);
1024
1025         /*
1026          * FIXME: reuse code from method_encode_signature().
1027          */
1028         SigBuffer buf;
1029         int i;
1030         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1031         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1032         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1033         guint32 idx;
1034
1035         sigbuffer_init (&buf, 32);
1036         /* LAMESPEC: all the call conv spec is foobared */
1037         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1038         if (mb->call_conv & 2)
1039                 idx |= 0x5; /* vararg */
1040         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1041                 idx |= 0x20; /* hasthis */
1042         if (ngparams)
1043                 idx |= 0x10; /* generic */
1044         sigbuffer_add_byte (&buf, idx);
1045         if (ngparams)
1046                 sigbuffer_add_value (&buf, ngparams);
1047         sigbuffer_add_value (&buf, nparams + notypes);
1048         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1049         if (!is_ok (error))
1050                 goto leave;
1051         encode_reflection_type (assembly, mb->rtype, &buf, error);
1052         if (!is_ok (error))
1053                 goto leave;
1054         for (i = 0; i < nparams; ++i) {
1055                 MonoArray *modreq = NULL;
1056                 MonoArray *modopt = NULL;
1057                 MonoReflectionType *pt;
1058
1059                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1060                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1061                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1062                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1063                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1064                 if (!is_ok (error))
1065                         goto leave;
1066                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1067                 encode_reflection_type (assembly, pt, &buf, error);
1068                 if (!is_ok (error))
1069                         goto leave;
1070         }
1071         if (notypes)
1072                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1073         for (i = 0; i < notypes; ++i) {
1074                 MonoReflectionType *pt;
1075
1076                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1077                 encode_reflection_type (assembly, pt, &buf, error);
1078                 if (!is_ok (error))
1079                         goto leave;
1080         }
1081
1082         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1083 leave:
1084         sigbuffer_free (&buf);
1085         return idx;
1086 }
1087
1088 static guint32
1089 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1090 {
1091         MONO_REQ_GC_UNSAFE_MODE;
1092
1093         mono_error_init (error);
1094
1095         MonoDynamicTable *table;
1096         guint32 *values;
1097         guint32 idx, sig_idx;
1098         guint nl = mono_array_length (ilgen->locals);
1099         SigBuffer buf;
1100         int i;
1101
1102         sigbuffer_init (&buf, 32);
1103         sigbuffer_add_value (&buf, 0x07);
1104         sigbuffer_add_value (&buf, nl);
1105         for (i = 0; i < nl; ++i) {
1106                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1107                 
1108                 if (lb->is_pinned)
1109                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1110                 
1111                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1112                 if (!is_ok (error)) {
1113                         sigbuffer_free (&buf);
1114                         return 0;
1115                 }
1116         }
1117         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1118         sigbuffer_free (&buf);
1119
1120         if (assembly->standalonesig_cache == NULL)
1121                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1122         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1123         if (idx)
1124                 return idx;
1125
1126         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1127         idx = table->next_idx ++;
1128         table->rows ++;
1129         alloc_table (table, table->rows);
1130         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1131
1132         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1133
1134         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1135
1136         return idx;
1137 }
1138
1139 static guint32
1140 method_count_clauses (MonoReflectionILGen *ilgen)
1141 {
1142         MONO_REQ_GC_UNSAFE_MODE;
1143
1144         guint32 num_clauses = 0;
1145         int i;
1146
1147         MonoILExceptionInfo *ex_info;
1148         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1149                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1150                 if (ex_info->handlers)
1151                         num_clauses += mono_array_length (ex_info->handlers);
1152                 else
1153                         num_clauses++;
1154         }
1155
1156         return num_clauses;
1157 }
1158
1159 #ifndef DISABLE_REFLECTION_EMIT
1160 static MonoExceptionClause*
1161 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1162 {
1163         MONO_REQ_GC_UNSAFE_MODE;
1164
1165         mono_error_init (error);
1166
1167         MonoExceptionClause *clauses;
1168         MonoExceptionClause *clause;
1169         MonoILExceptionInfo *ex_info;
1170         MonoILExceptionBlock *ex_block;
1171         guint32 finally_start;
1172         int i, j, clause_index;;
1173
1174         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1175
1176         clause_index = 0;
1177         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1178                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1179                 finally_start = ex_info->start + ex_info->len;
1180                 if (!ex_info->handlers)
1181                         continue;
1182                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1183                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1184                         clause = &(clauses [clause_index]);
1185
1186                         clause->flags = ex_block->type;
1187                         clause->try_offset = ex_info->start;
1188
1189                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1190                                 clause->try_len = finally_start - ex_info->start;
1191                         else
1192                                 clause->try_len = ex_info->len;
1193                         clause->handler_offset = ex_block->start;
1194                         clause->handler_len = ex_block->len;
1195                         if (ex_block->extype) {
1196                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1197
1198                                 if (!is_ok (error)) {
1199                                         image_g_free (image, clauses);
1200                                         return NULL;
1201                                 }
1202                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1203                         } else {
1204                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1205                                         clause->data.filter_offset = ex_block->filter_offset;
1206                                 else
1207                                         clause->data.filter_offset = 0;
1208                         }
1209                         finally_start = ex_block->start + ex_block->len;
1210
1211                         clause_index ++;
1212                 }
1213         }
1214
1215         return clauses;
1216 }
1217 #endif /* !DISABLE_REFLECTION_EMIT */
1218
1219 /**
1220  * method_encode_code:
1221  *
1222  * @assembly the assembly
1223  * @mb the managed MethodBuilder
1224  * @error set on error
1225  *
1226  * Note that the return value is not sensible if @error is set.
1227  */
1228 static guint32
1229 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1230 {
1231         MONO_REQ_GC_UNSAFE_MODE;
1232
1233         char flags = 0;
1234         guint32 idx;
1235         guint32 code_size;
1236         gint32 max_stack, i;
1237         gint32 num_locals = 0;
1238         gint32 num_exception = 0;
1239         gint maybe_small;
1240         guint32 fat_flags;
1241         char fat_header [12];
1242         guint32 int_value;
1243         guint16 short_value;
1244         guint32 local_sig = 0;
1245         guint32 header_size = 12;
1246         MonoArray *code;
1247
1248         mono_error_init (error);
1249
1250         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1251                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1252                 return 0;
1253
1254         /*if (mb->name)
1255                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1256         if (mb->ilgen) {
1257                 code = mb->ilgen->code;
1258                 code_size = mb->ilgen->code_len;
1259                 max_stack = mb->ilgen->max_stack;
1260                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1261                 if (mb->ilgen->ex_handlers)
1262                         num_exception = method_count_clauses (mb->ilgen);
1263         } else {
1264                 code = mb->code;
1265                 if (code == NULL){
1266                         char *name = mono_string_to_utf8 (mb->name);
1267                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1268                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1269                         g_free (str);
1270                         g_free (name);
1271                         return 0;
1272                 }
1273
1274                 code_size = mono_array_length (code);
1275                 max_stack = 8; /* we probably need to run a verifier on the code... */
1276         }
1277
1278         stream_data_align (&assembly->code);
1279
1280         /* check for exceptions, maxstack, locals */
1281         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1282         if (maybe_small) {
1283                 if (code_size < 64 && !(code_size & 1)) {
1284                         flags = (code_size << 2) | 0x2;
1285                 } else if (code_size < 32 && (code_size & 1)) {
1286                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1287                 } else {
1288                         goto fat_header;
1289                 }
1290                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1291                 /* add to the fixup todo list */
1292                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1293                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1294                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1295                 return assembly->text_rva + idx;
1296         } 
1297 fat_header:
1298         if (num_locals) {
1299                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1300                 return_val_if_nok (error, 0);
1301         }
1302         /* 
1303          * FIXME: need to set also the header size in fat_flags.
1304          * (and more sects and init locals flags)
1305          */
1306         fat_flags =  0x03;
1307         if (num_exception)
1308                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1309         if (mb->init_locals)
1310                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1311         fat_header [0] = fat_flags;
1312         fat_header [1] = (header_size / 4 ) << 4;
1313         short_value = GUINT16_TO_LE (max_stack);
1314         memcpy (fat_header + 2, &short_value, 2);
1315         int_value = GUINT32_TO_LE (code_size);
1316         memcpy (fat_header + 4, &int_value, 4);
1317         int_value = GUINT32_TO_LE (local_sig);
1318         memcpy (fat_header + 8, &int_value, 4);
1319         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1320         /* add to the fixup todo list */
1321         if (mb->ilgen && mb->ilgen->num_token_fixups)
1322                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1323         
1324         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1325         if (num_exception) {
1326                 unsigned char sheader [4];
1327                 MonoILExceptionInfo * ex_info;
1328                 MonoILExceptionBlock * ex_block;
1329                 int j;
1330
1331                 stream_data_align (&assembly->code);
1332                 /* always use fat format for now */
1333                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1334                 num_exception *= 6 * sizeof (guint32);
1335                 num_exception += 4; /* include the size of the header */
1336                 sheader [1] = num_exception & 0xff;
1337                 sheader [2] = (num_exception >> 8) & 0xff;
1338                 sheader [3] = (num_exception >> 16) & 0xff;
1339                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1340                 /* fat header, so we are already aligned */
1341                 /* reverse order */
1342                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1343                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1344                         if (ex_info->handlers) {
1345                                 int finally_start = ex_info->start + ex_info->len;
1346                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1347                                         guint32 val;
1348                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1349                                         /* the flags */
1350                                         val = GUINT32_TO_LE (ex_block->type);
1351                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1352                                         /* try offset */
1353                                         val = GUINT32_TO_LE (ex_info->start);
1354                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1355                                         /* need fault, too, probably */
1356                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1357                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1358                                         else
1359                                                 val = GUINT32_TO_LE (ex_info->len);
1360                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361                                         /* handler offset */
1362                                         val = GUINT32_TO_LE (ex_block->start);
1363                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1364                                         /* handler len */
1365                                         val = GUINT32_TO_LE (ex_block->len);
1366                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1367                                         finally_start = ex_block->start + ex_block->len;
1368                                         if (ex_block->extype) {
1369                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1370                                                 return_val_if_nok (error, 0);
1371
1372                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1373                                         } else {
1374                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1375                                                         val = ex_block->filter_offset;
1376                                                 else
1377                                                         val = 0;
1378                                         }
1379                                         val = GUINT32_TO_LE (val);
1380                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1381                                         /*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", 
1382                                                         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);*/
1383                                 }
1384                         } else {
1385                                 g_error ("No clauses for ex info block %d", i);
1386                         }
1387                 }
1388         }
1389         return assembly->text_rva + idx;
1390 }
1391
1392 static guint32
1393 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1394 {
1395         MONO_REQ_GC_NEUTRAL_MODE;
1396
1397         int i;
1398         MonoDynamicTable *table;
1399         guint32 *values;
1400         
1401         table = &assembly->tables [table_idx];
1402
1403         g_assert (col < table->columns);
1404
1405         values = table->values + table->columns;
1406         for (i = 1; i <= table->rows; ++i) {
1407                 if (values [col] == token)
1408                         return i;
1409                 values += table->columns;
1410         }
1411         return 0;
1412 }
1413
1414 /*
1415  * LOCKING: Acquires the loader lock. 
1416  */
1417 static MonoCustomAttrInfo*
1418 lookup_custom_attr (MonoImage *image, gpointer member)
1419 {
1420         MONO_REQ_GC_NEUTRAL_MODE;
1421
1422         MonoCustomAttrInfo* res;
1423
1424         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1425
1426         if (!res)
1427                 return NULL;
1428
1429         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1430         res->cached = 0;
1431         return res;
1432 }
1433
1434 static gboolean
1435 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1436 {
1437         MONO_REQ_GC_UNSAFE_MODE;
1438
1439         /* FIXME: Need to do more checks */
1440         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1441                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1442
1443                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1444                         return FALSE;
1445         }
1446
1447         return TRUE;
1448 }
1449
1450 static MonoCustomAttrInfo*
1451 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1452 {
1453         MONO_REQ_GC_UNSAFE_MODE;
1454
1455         int i, index, count, not_visible;
1456         MonoCustomAttrInfo *ainfo;
1457         MonoReflectionCustomAttr *cattr;
1458
1459         if (!cattrs)
1460                 return NULL;
1461         /* FIXME: check in assembly the Run flag is set */
1462
1463         count = mono_array_length (cattrs);
1464
1465         /* Skip nonpublic attributes since MS.NET seems to do the same */
1466         /* FIXME: This needs to be done more globally */
1467         not_visible = 0;
1468         for (i = 0; i < count; ++i) {
1469                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1470                 if (!custom_attr_visible (image, cattr))
1471                         not_visible ++;
1472         }
1473         count -= not_visible;
1474
1475         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1476
1477         ainfo->image = image;
1478         ainfo->num_attrs = count;
1479         ainfo->cached = alloc_img != NULL;
1480         index = 0;
1481         for (i = 0; i < count; ++i) {
1482                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1483                 if (custom_attr_visible (image, cattr)) {
1484                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1485                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1486                         ainfo->attrs [index].ctor = cattr->ctor->method;
1487                         ainfo->attrs [index].data = saved;
1488                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1489                         index ++;
1490                 }
1491         }
1492
1493         return ainfo;
1494 }
1495
1496 #ifndef DISABLE_REFLECTION_EMIT
1497 /*
1498  * LOCKING: Acquires the loader lock. 
1499  */
1500 static void
1501 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1502 {
1503         MONO_REQ_GC_UNSAFE_MODE;
1504
1505         MonoCustomAttrInfo *ainfo, *tmp;
1506
1507         if (!cattrs || !mono_array_length (cattrs))
1508                 return;
1509
1510         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1511
1512         mono_loader_lock ();
1513         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1514         if (tmp)
1515                 mono_custom_attrs_free (tmp);
1516         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1517         mono_loader_unlock ();
1518
1519 }
1520 #endif
1521
1522 void
1523 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1524 {
1525         MONO_REQ_GC_NEUTRAL_MODE;
1526
1527         if (ainfo && !ainfo->cached)
1528                 g_free (ainfo);
1529 }
1530
1531 /*
1532  * idx is the table index of the object
1533  * type is one of MONO_CUSTOM_ATTR_*
1534  */
1535 static gboolean
1536 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1537 {
1538         MONO_REQ_GC_UNSAFE_MODE;
1539
1540         MonoDynamicTable *table;
1541         MonoReflectionCustomAttr *cattr;
1542         guint32 *values;
1543         guint32 count, i, token;
1544         char blob_size [6];
1545         char *p = blob_size;
1546         
1547         mono_error_init (error);
1548
1549         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1550         if (!cattrs)
1551                 return TRUE;
1552         count = mono_array_length (cattrs);
1553         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1554         table->rows += count;
1555         alloc_table (table, table->rows);
1556         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1557         idx <<= MONO_CUSTOM_ATTR_BITS;
1558         idx |= type;
1559         for (i = 0; i < count; ++i) {
1560                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1561                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1562                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1563                 if (!mono_error_ok (error)) goto fail;
1564                 type = mono_metadata_token_index (token);
1565                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1566                 switch (mono_metadata_token_table (token)) {
1567                 case MONO_TABLE_METHOD:
1568                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1569                         /*
1570                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1571                          * method, not the one returned by mono_image_create_token ().
1572                          */
1573                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1574                         break;
1575                 case MONO_TABLE_MEMBERREF:
1576                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1577                         break;
1578                 default:
1579                         g_warning ("got wrong token in custom attr");
1580                         continue;
1581                 }
1582                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1583                 p = blob_size;
1584                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1585                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1586                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1587                 values += MONO_CUSTOM_ATTR_SIZE;
1588                 ++table->next_idx;
1589         }
1590
1591         return TRUE;
1592
1593 fail:
1594         return FALSE;
1595 }
1596
1597 static void
1598 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1599 {
1600         MONO_REQ_GC_UNSAFE_MODE;
1601
1602         MonoDynamicTable *table;
1603         guint32 *values;
1604         guint32 count, i, idx;
1605         MonoReflectionPermissionSet *perm;
1606
1607         if (!permissions)
1608                 return;
1609
1610         count = mono_array_length (permissions);
1611         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1612         table->rows += count;
1613         alloc_table (table, table->rows);
1614
1615         for (i = 0; i < mono_array_length (permissions); ++i) {
1616                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1617
1618                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1619
1620                 idx = mono_metadata_token_index (parent_token);
1621                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1622                 switch (mono_metadata_token_table (parent_token)) {
1623                 case MONO_TABLE_TYPEDEF:
1624                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1625                         break;
1626                 case MONO_TABLE_METHOD:
1627                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1628                         break;
1629                 case MONO_TABLE_ASSEMBLY:
1630                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1631                         break;
1632                 default:
1633                         g_assert_not_reached ();
1634                 }
1635
1636                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1637                 values [MONO_DECL_SECURITY_PARENT] = idx;
1638                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1639
1640                 ++table->next_idx;
1641         }
1642 }
1643
1644 /*
1645  * Fill in the MethodDef and ParamDef tables for a method.
1646  * This is used for both normal methods and constructors.
1647  */
1648 static gboolean
1649 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1650 {
1651         MONO_REQ_GC_UNSAFE_MODE;
1652
1653         MonoDynamicTable *table;
1654         guint32 *values;
1655         guint i, count;
1656
1657         mono_error_init (error);
1658
1659         /* room in this table is already allocated */
1660         table = &assembly->tables [MONO_TABLE_METHOD];
1661         *mb->table_idx = table->next_idx ++;
1662         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1663         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1664         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1665         values [MONO_METHOD_FLAGS] = mb->attrs;
1666         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1667         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1670         return_val_if_nok (error, FALSE);
1671
1672         table = &assembly->tables [MONO_TABLE_PARAM];
1673         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1674
1675         mono_image_add_decl_security (assembly, 
1676                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1677
1678         if (mb->pinfo) {
1679                 MonoDynamicTable *mtable;
1680                 guint32 *mvalues;
1681                 
1682                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1683                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1684                 
1685                 count = 0;
1686                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1687                         if (mono_array_get (mb->pinfo, gpointer, i))
1688                                 count++;
1689                 }
1690                 table->rows += count;
1691                 alloc_table (table, table->rows);
1692                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1693                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1694                         MonoReflectionParamBuilder *pb;
1695                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1696                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1697                                 values [MONO_PARAM_SEQUENCE] = i;
1698                                 if (pb->name != NULL) {
1699                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1700                                 } else {
1701                                         values [MONO_PARAM_NAME] = 0;
1702                                 }
1703                                 values += MONO_PARAM_SIZE;
1704                                 if (pb->marshal_info) {
1705                                         mtable->rows++;
1706                                         alloc_table (mtable, mtable->rows);
1707                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1708                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1709                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1710                                         return_val_if_nok (error, FALSE);
1711                                 }
1712                                 pb->table_idx = table->next_idx++;
1713                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1714                                         guint32 field_type = 0;
1715                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1716                                         mtable->rows ++;
1717                                         alloc_table (mtable, mtable->rows);
1718                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1719                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1720                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1721                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1722                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1723                                 }
1724                         }
1725                 }
1726         }
1727
1728         return TRUE;
1729 }
1730
1731 #ifndef DISABLE_REFLECTION_EMIT
1732 static gboolean
1733 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1734 {
1735         MONO_REQ_GC_UNSAFE_MODE;
1736
1737         mono_error_init (error);
1738         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1739
1740         rmb->ilgen = mb->ilgen;
1741         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1742         return_val_if_nok (error, FALSE);
1743         rmb->parameters = mb->parameters;
1744         rmb->generic_params = mb->generic_params;
1745         rmb->generic_container = mb->generic_container;
1746         rmb->opt_types = NULL;
1747         rmb->pinfo = mb->pinfo;
1748         rmb->attrs = mb->attrs;
1749         rmb->iattrs = mb->iattrs;
1750         rmb->call_conv = mb->call_conv;
1751         rmb->code = mb->code;
1752         rmb->type = mb->type;
1753         rmb->name = mb->name;
1754         rmb->table_idx = &mb->table_idx;
1755         rmb->init_locals = mb->init_locals;
1756         rmb->skip_visibility = FALSE;
1757         rmb->return_modreq = mb->return_modreq;
1758         rmb->return_modopt = mb->return_modopt;
1759         rmb->param_modreq = mb->param_modreq;
1760         rmb->param_modopt = mb->param_modopt;
1761         rmb->permissions = mb->permissions;
1762         rmb->mhandle = mb->mhandle;
1763         rmb->nrefs = 0;
1764         rmb->refs = NULL;
1765
1766         if (mb->dll) {
1767                 rmb->charset = mb->charset;
1768                 rmb->extra_flags = mb->extra_flags;
1769                 rmb->native_cc = mb->native_cc;
1770                 rmb->dllentry = mb->dllentry;
1771                 rmb->dll = mb->dll;
1772         }
1773
1774         return TRUE;
1775 }
1776
1777 static gboolean
1778 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1779 {
1780         MONO_REQ_GC_UNSAFE_MODE;
1781
1782         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1783
1784         mono_error_init (error);
1785
1786         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1787
1788         rmb->ilgen = mb->ilgen;
1789         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1790         return_val_if_nok (error, FALSE);
1791         rmb->parameters = mb->parameters;
1792         rmb->generic_params = NULL;
1793         rmb->generic_container = NULL;
1794         rmb->opt_types = NULL;
1795         rmb->pinfo = mb->pinfo;
1796         rmb->attrs = mb->attrs;
1797         rmb->iattrs = mb->iattrs;
1798         rmb->call_conv = mb->call_conv;
1799         rmb->code = NULL;
1800         rmb->type = mb->type;
1801         rmb->name = mono_string_new (mono_domain_get (), name);
1802         rmb->table_idx = &mb->table_idx;
1803         rmb->init_locals = mb->init_locals;
1804         rmb->skip_visibility = FALSE;
1805         rmb->return_modreq = NULL;
1806         rmb->return_modopt = NULL;
1807         rmb->param_modreq = mb->param_modreq;
1808         rmb->param_modopt = mb->param_modopt;
1809         rmb->permissions = mb->permissions;
1810         rmb->mhandle = mb->mhandle;
1811         rmb->nrefs = 0;
1812         rmb->refs = NULL;
1813
1814         return TRUE;
1815 }
1816
1817 static void
1818 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1819 {
1820         MONO_REQ_GC_UNSAFE_MODE;
1821
1822         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1823
1824         rmb->ilgen = mb->ilgen;
1825         rmb->rtype = mb->rtype;
1826         rmb->parameters = mb->parameters;
1827         rmb->generic_params = NULL;
1828         rmb->generic_container = NULL;
1829         rmb->opt_types = NULL;
1830         rmb->pinfo = NULL;
1831         rmb->attrs = mb->attrs;
1832         rmb->iattrs = 0;
1833         rmb->call_conv = mb->call_conv;
1834         rmb->code = NULL;
1835         rmb->type = (MonoObject *) mb->owner;
1836         rmb->name = mb->name;
1837         rmb->table_idx = NULL;
1838         rmb->init_locals = mb->init_locals;
1839         rmb->skip_visibility = mb->skip_visibility;
1840         rmb->return_modreq = NULL;
1841         rmb->return_modopt = NULL;
1842         rmb->param_modreq = NULL;
1843         rmb->param_modopt = NULL;
1844         rmb->permissions = NULL;
1845         rmb->mhandle = mb->mhandle;
1846         rmb->nrefs = 0;
1847         rmb->refs = NULL;
1848 }       
1849 #endif
1850
1851 static gboolean
1852 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1853 {
1854         MONO_REQ_GC_UNSAFE_MODE;
1855
1856         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1857         MonoDynamicTable *table;
1858         guint32 *values;
1859         guint32 tok;
1860         MonoReflectionMethod *m;
1861         int i;
1862
1863         mono_error_init (error);
1864
1865         if (!mb->override_methods)
1866                 return TRUE;
1867
1868         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1869                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1870
1871                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1872                 table->rows ++;
1873                 alloc_table (table, table->rows);
1874                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1875                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1876                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1877
1878                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1879                 return_val_if_nok (error, FALSE);
1880
1881                 switch (mono_metadata_token_table (tok)) {
1882                 case MONO_TABLE_MEMBERREF:
1883                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1884                         break;
1885                 case MONO_TABLE_METHOD:
1886                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1887                         break;
1888                 default:
1889                         g_assert_not_reached ();
1890                 }
1891                 values [MONO_METHODIMPL_DECLARATION] = tok;
1892         }
1893
1894         return TRUE;
1895 }
1896
1897 #ifndef DISABLE_REFLECTION_EMIT
1898 static gboolean
1899 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1900 {
1901         MONO_REQ_GC_UNSAFE_MODE;
1902
1903         MonoDynamicTable *table;
1904         guint32 *values;
1905         ReflectionMethodBuilder rmb;
1906         int i;
1907
1908         mono_error_init (error);
1909
1910         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1911             !mono_image_basic_method (&rmb, assembly, error))
1912                 return FALSE;
1913
1914         mb->table_idx = *rmb.table_idx;
1915
1916         if (mb->dll) { /* It's a P/Invoke method */
1917                 guint32 moduleref;
1918                 /* map CharSet values to on-disk values */
1919                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1920                 int extra_flags = mb->extra_flags;
1921                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1922                 table->rows ++;
1923                 alloc_table (table, table->rows);
1924                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1925                 
1926                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1927                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1928                 if (mb->dllentry)
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1930                 else
1931                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1932                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1933                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1934                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1935                         table->rows ++;
1936                         alloc_table (table, table->rows);
1937                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1938                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1939                 }
1940         }
1941
1942         if (mb->generic_params) {
1943                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1944                 table->rows += mono_array_length (mb->generic_params);
1945                 alloc_table (table, table->rows);
1946                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1947                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1948
1949                         mono_image_get_generic_param_info (
1950                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1951                 }
1952         }
1953
1954         return TRUE;
1955 }
1956
1957 static gboolean
1958 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1959 {
1960         MONO_REQ_GC_UNSAFE_MODE;
1961
1962         ReflectionMethodBuilder rmb;
1963
1964         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1965                 return FALSE;
1966
1967         if (!mono_image_basic_method (&rmb, assembly, error))
1968                 return FALSE;
1969
1970         mb->table_idx = *rmb.table_idx;
1971
1972         return TRUE;
1973 }
1974 #endif
1975
1976 static char*
1977 type_get_fully_qualified_name (MonoType *type)
1978 {
1979         MONO_REQ_GC_NEUTRAL_MODE;
1980
1981         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1982 }
1983
1984 static char*
1985 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1986 {
1987         MONO_REQ_GC_UNSAFE_MODE;
1988
1989         MonoClass *klass;
1990         MonoAssembly *ta;
1991
1992         klass = mono_class_from_mono_type (type);
1993         if (!klass) 
1994                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1995         ta = klass->image->assembly;
1996         if (assembly_is_dynamic (ta) || (ta == ass)) {
1997                 if (klass->generic_class || klass->generic_container)
1998                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2000                 else
2001                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2002         }
2003
2004         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2005 }
2006
2007 #ifndef DISABLE_REFLECTION_EMIT
2008 /*field_image is the image to which the eventual custom mods have been encoded against*/
2009 static guint32
2010 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2011 {
2012         MONO_REQ_GC_NEUTRAL_MODE;
2013
2014         SigBuffer buf;
2015         guint32 idx, i, token;
2016
2017         if (!assembly->save)
2018                 return 0;
2019
2020         sigbuffer_init (&buf, 32);
2021         
2022         sigbuffer_add_value (&buf, 0x06);
2023         /* encode custom attributes before the type */
2024         if (type->num_mods) {
2025                 for (i = 0; i < type->num_mods; ++i) {
2026                         if (field_image) {
2027                                 MonoError error;
2028                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2029                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2030
2031                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2032                         } else {
2033                                 token = type->modifiers [i].token;
2034                         }
2035
2036                         if (type->modifiers [i].required)
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2038                         else
2039                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2040
2041                         sigbuffer_add_value (&buf, token);
2042                 }
2043         }
2044         encode_type (assembly, type, &buf);
2045         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2046         sigbuffer_free (&buf);
2047         return idx;
2048 }
2049 #endif
2050
2051 static guint32
2052 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2053 {
2054         MONO_REQ_GC_UNSAFE_MODE;
2055
2056         mono_error_init (error);
2057
2058         SigBuffer buf;
2059         guint32 idx;
2060         guint32 typespec = 0;
2061         MonoType *type;
2062         MonoClass *klass;
2063
2064         init_type_builder_generics (fb->type);
2065
2066         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2067         return_val_if_nok (error, 0);
2068         klass = mono_class_from_mono_type (type);
2069
2070         sigbuffer_init (&buf, 32);
2071         
2072         sigbuffer_add_value (&buf, 0x06);
2073         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2074         if (!is_ok (error))
2075                 goto fail;
2076         /* encode custom attributes before the type */
2077
2078         if (klass->generic_container)
2079                 typespec = create_typespec (assembly, type);
2080
2081         if (typespec) {
2082                 MonoGenericClass *gclass;
2083                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2084                 encode_generic_class (assembly, gclass, &buf);
2085         } else {
2086                 encode_type (assembly, type, &buf);
2087         }
2088         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089         sigbuffer_free (&buf);
2090         return idx;
2091 fail:
2092         sigbuffer_free (&buf);
2093         return 0;
2094 }
2095
2096 static guint32
2097 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2098 {
2099         MONO_REQ_GC_UNSAFE_MODE;
2100
2101         char blob_size [64];
2102         char *b = blob_size;
2103         char *box_val;
2104         char* buf;
2105         guint32 idx = 0, len = 0, dummy = 0;
2106
2107         buf = (char *)g_malloc (64);
2108         if (!val) {
2109                 *ret_type = MONO_TYPE_CLASS;
2110                 len = 4;
2111                 box_val = (char*)&dummy;
2112         } else {
2113                 box_val = ((char*)val) + sizeof (MonoObject);
2114                 *ret_type = val->vtable->klass->byval_arg.type;
2115         }
2116 handle_enum:
2117         switch (*ret_type) {
2118         case MONO_TYPE_BOOLEAN:
2119         case MONO_TYPE_U1:
2120         case MONO_TYPE_I1:
2121                 len = 1;
2122                 break;
2123         case MONO_TYPE_CHAR:
2124         case MONO_TYPE_U2:
2125         case MONO_TYPE_I2:
2126                 len = 2;
2127                 break;
2128         case MONO_TYPE_U4:
2129         case MONO_TYPE_I4:
2130         case MONO_TYPE_R4:
2131                 len = 4;
2132                 break;
2133         case MONO_TYPE_U8:
2134         case MONO_TYPE_I8:
2135                 len = 8;
2136                 break;
2137         case MONO_TYPE_R8:
2138                 len = 8;
2139                 break;
2140         case MONO_TYPE_VALUETYPE: {
2141                 MonoClass *klass = val->vtable->klass;
2142                 
2143                 if (klass->enumtype) {
2144                         *ret_type = mono_class_enum_basetype (klass)->type;
2145                         goto handle_enum;
2146                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2147                         len = 8;
2148                 } else 
2149                         g_error ("we can't encode valuetypes, we should have never reached this line");
2150                 break;
2151         }
2152         case MONO_TYPE_CLASS:
2153                 break;
2154         case MONO_TYPE_STRING: {
2155                 MonoString *str = (MonoString*)val;
2156                 /* there is no signature */
2157                 len = str->length * 2;
2158                 mono_metadata_encode_value (len, b, &b);
2159 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2160                 {
2161                         char *swapped = g_malloc (2 * mono_string_length (str));
2162                         const char *p = (const char*)mono_string_chars (str);
2163
2164                         swap_with_size (swapped, p, 2, mono_string_length (str));
2165                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2166                         g_free (swapped);
2167                 }
2168 #else
2169                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2170 #endif
2171
2172                 g_free (buf);
2173                 return idx;
2174         }
2175         case MONO_TYPE_GENERICINST:
2176                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2177                 goto handle_enum;
2178         default:
2179                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2180         }
2181
2182         /* there is no signature */
2183         mono_metadata_encode_value (len, b, &b);
2184 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2185         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2186         swap_with_size (blob_size, box_val, len, 1);
2187         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2188 #else
2189         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2190 #endif
2191
2192         g_free (buf);
2193         return idx;
2194 }
2195
2196 static guint32
2197 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2198 {
2199         MONO_REQ_GC_UNSAFE_MODE;
2200
2201         mono_error_init (error);
2202
2203         char *str;
2204         SigBuffer buf;
2205         guint32 idx, len;
2206
2207         sigbuffer_init (&buf, 32);
2208
2209         sigbuffer_add_value (&buf, minfo->type);
2210
2211         switch (minfo->type) {
2212         case MONO_NATIVE_BYVALTSTR:
2213         case MONO_NATIVE_BYVALARRAY:
2214                 sigbuffer_add_value (&buf, minfo->count);
2215                 break;
2216         case MONO_NATIVE_LPARRAY:
2217                 if (minfo->eltype || minfo->has_size) {
2218                         sigbuffer_add_value (&buf, minfo->eltype);
2219                         if (minfo->has_size) {
2220                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2221                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2222
2223                                 /* LAMESPEC: ElemMult is undocumented */
2224                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2225                         }
2226                 }
2227                 break;
2228         case MONO_NATIVE_SAFEARRAY:
2229                 if (minfo->eltype)
2230                         sigbuffer_add_value (&buf, minfo->eltype);
2231                 break;
2232         case MONO_NATIVE_CUSTOM:
2233                 if (minfo->guid) {
2234                         str = mono_string_to_utf8 (minfo->guid);
2235                         len = strlen (str);
2236                         sigbuffer_add_value (&buf, len);
2237                         sigbuffer_add_mem (&buf, str, len);
2238                         g_free (str);
2239                 } else {
2240                         sigbuffer_add_value (&buf, 0);
2241                 }
2242                 /* native type name */
2243                 sigbuffer_add_value (&buf, 0);
2244                 /* custom marshaler type name */
2245                 if (minfo->marshaltype || minfo->marshaltyperef) {
2246                         if (minfo->marshaltyperef) {
2247                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2248                                 if (!is_ok (error)) {
2249                                         sigbuffer_free (&buf);
2250                                         return 0;
2251                                 }
2252                                 str = type_get_fully_qualified_name (marshaltype);
2253                         } else
2254                                 str = mono_string_to_utf8 (minfo->marshaltype);
2255                         len = strlen (str);
2256                         sigbuffer_add_value (&buf, len);
2257                         sigbuffer_add_mem (&buf, str, len);
2258                         g_free (str);
2259                 } else {
2260                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2261                         sigbuffer_add_value (&buf, 0);
2262                 }
2263                 if (minfo->mcookie) {
2264                         str = mono_string_to_utf8 (minfo->mcookie);
2265                         len = strlen (str);
2266                         sigbuffer_add_value (&buf, len);
2267                         sigbuffer_add_mem (&buf, str, len);
2268                         g_free (str);
2269                 } else {
2270                         sigbuffer_add_value (&buf, 0);
2271                 }
2272                 break;
2273         default:
2274                 break;
2275         }
2276         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2277         sigbuffer_free (&buf);
2278         return idx;
2279 }
2280
2281 static void
2282 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2283 {
2284         MONO_REQ_GC_UNSAFE_MODE;
2285
2286         mono_error_init (error);
2287
2288         MonoDynamicTable *table;
2289         guint32 *values;
2290
2291         /* maybe this fixup should be done in the C# code */
2292         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2293                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2294         table = &assembly->tables [MONO_TABLE_FIELD];
2295         fb->table_idx = table->next_idx ++;
2296         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2297         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2298         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2299         values [MONO_FIELD_FLAGS] = fb->attrs;
2300         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2301         return_if_nok (error);
2302
2303
2304         if (fb->offset != -1) {
2305                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2306                 table->rows ++;
2307                 alloc_table (table, table->rows);
2308                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2309                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2310                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2311         }
2312         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2313                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2314                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2315                 table->rows ++;
2316                 alloc_table (table, table->rows);
2317                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2318                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2319                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2320                 values [MONO_CONSTANT_TYPE] = field_type;
2321                 values [MONO_CONSTANT_PADDING] = 0;
2322         }
2323         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2324                 guint32 rva_idx;
2325                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2326                 table->rows ++;
2327                 alloc_table (table, table->rows);
2328                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2329                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2330                 /*
2331                  * We store it in the code section because it's simpler for now.
2332                  */
2333                 if (fb->rva_data) {
2334                         if (mono_array_length (fb->rva_data) >= 10)
2335                                 stream_data_align (&assembly->code);
2336                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2337                 } else
2338                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2339                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2340         }
2341         if (fb->marshal_info) {
2342                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2343                 table->rows ++;
2344                 alloc_table (table, table->rows);
2345                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2346                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2347                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2348                 return_if_nok (error);
2349         }
2350 }
2351
2352 static guint32
2353 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2354 {
2355         MONO_REQ_GC_UNSAFE_MODE;
2356
2357         mono_error_init (error);
2358
2359         SigBuffer buf;
2360         guint32 nparams = 0;
2361         MonoReflectionMethodBuilder *mb = fb->get_method;
2362         MonoReflectionMethodBuilder *smb = fb->set_method;
2363         guint32 idx, i;
2364
2365         if (mb && mb->parameters)
2366                 nparams = mono_array_length (mb->parameters);
2367         if (!mb && smb && smb->parameters)
2368                 nparams = mono_array_length (smb->parameters) - 1;
2369         sigbuffer_init (&buf, 32);
2370         if (fb->call_conv & 0x20)
2371                 sigbuffer_add_byte (&buf, 0x28);
2372         else
2373                 sigbuffer_add_byte (&buf, 0x08);
2374         sigbuffer_add_value (&buf, nparams);
2375         if (mb) {
2376                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2377                 if (!is_ok (error))
2378                         goto fail;
2379                 for (i = 0; i < nparams; ++i) {
2380                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2381                         encode_reflection_type (assembly, pt, &buf, error);
2382                         if (!is_ok (error))
2383                                 goto fail;
2384                 }
2385         } else if (smb && smb->parameters) {
2386                 /* the property type is the last param */
2387                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2388                 if (!is_ok (error))
2389                         goto fail;
2390
2391                 for (i = 0; i < nparams; ++i) {
2392                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2393                         encode_reflection_type (assembly, pt, &buf, error);
2394                         if (!is_ok (error))
2395                                 goto fail;
2396                 }
2397         } else {
2398                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2399                 if (!is_ok (error))
2400                         goto fail;
2401         }
2402
2403         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2404         sigbuffer_free (&buf);
2405         return idx;
2406 fail:
2407         sigbuffer_free (&buf);
2408         return 0;
2409 }
2410
2411 static void
2412 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2413 {
2414         MONO_REQ_GC_UNSAFE_MODE;
2415
2416         mono_error_init (error);
2417
2418         MonoDynamicTable *table;
2419         guint32 *values;
2420         guint num_methods = 0;
2421         guint32 semaidx;
2422
2423         /* 
2424          * we need to set things in the following tables:
2425          * PROPERTYMAP (info already filled in _get_type_info ())
2426          * PROPERTY    (rows already preallocated in _get_type_info ())
2427          * METHOD      (method info already done with the generic method code)
2428          * METHODSEMANTICS
2429          * CONSTANT
2430          */
2431         table = &assembly->tables [MONO_TABLE_PROPERTY];
2432         pb->table_idx = table->next_idx ++;
2433         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2434         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2435         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2436         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2437         return_if_nok (error);
2438
2439
2440         /* FIXME: we still don't handle 'other' methods */
2441         if (pb->get_method) num_methods ++;
2442         if (pb->set_method) num_methods ++;
2443
2444         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2445         table->rows += num_methods;
2446         alloc_table (table, table->rows);
2447
2448         if (pb->get_method) {
2449                 semaidx = table->next_idx ++;
2450                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2452                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2453                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2454         }
2455         if (pb->set_method) {
2456                 semaidx = table->next_idx ++;
2457                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2458                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2459                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2460                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2461         }
2462         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2463                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2464                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2465                 table->rows ++;
2466                 alloc_table (table, table->rows);
2467                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2468                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2469                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2470                 values [MONO_CONSTANT_TYPE] = field_type;
2471                 values [MONO_CONSTANT_PADDING] = 0;
2472         }
2473 }
2474
2475 static void
2476 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2477 {
2478         MONO_REQ_GC_UNSAFE_MODE;
2479
2480         MonoDynamicTable *table;
2481         guint32 *values;
2482         guint num_methods = 0;
2483         guint32 semaidx;
2484
2485         /* 
2486          * we need to set things in the following tables:
2487          * EVENTMAP (info already filled in _get_type_info ())
2488          * EVENT    (rows already preallocated in _get_type_info ())
2489          * METHOD      (method info already done with the generic method code)
2490          * METHODSEMANTICS
2491          */
2492         table = &assembly->tables [MONO_TABLE_EVENT];
2493         eb->table_idx = table->next_idx ++;
2494         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2495         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2496         values [MONO_EVENT_FLAGS] = eb->attrs;
2497         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2498         return_if_nok (error);
2499         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2500
2501         /*
2502          * FIXME: we still don't handle 'other' methods 
2503          */
2504         if (eb->add_method) num_methods ++;
2505         if (eb->remove_method) num_methods ++;
2506         if (eb->raise_method) num_methods ++;
2507
2508         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2509         table->rows += num_methods;
2510         alloc_table (table, table->rows);
2511
2512         if (eb->add_method) {
2513                 semaidx = table->next_idx ++;
2514                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2515                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2516                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2517                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2518         }
2519         if (eb->remove_method) {
2520                 semaidx = table->next_idx ++;
2521                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2522                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2523                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2524                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2525         }
2526         if (eb->raise_method) {
2527                 semaidx = table->next_idx ++;
2528                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2529                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2530                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2531                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2532         }
2533 }
2534
2535 static void
2536 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2537 {
2538         MONO_REQ_GC_UNSAFE_MODE;
2539
2540         mono_error_init (error);
2541
2542         MonoDynamicTable *table;
2543         guint32 num_constraints, i;
2544         guint32 *values;
2545         guint32 table_idx;
2546
2547         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2548         num_constraints = gparam->iface_constraints ?
2549                 mono_array_length (gparam->iface_constraints) : 0;
2550         table->rows += num_constraints;
2551         if (gparam->base_type)
2552                 table->rows++;
2553         alloc_table (table, table->rows);
2554
2555         if (gparam->base_type) {
2556                 table_idx = table->next_idx ++;
2557                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2558
2559                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2560                 return_if_nok (error);
2561                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2562                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2563         }
2564
2565         for (i = 0; i < num_constraints; i++) {
2566                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2567                         gparam->iface_constraints, gpointer, i);
2568
2569                 table_idx = table->next_idx ++;
2570                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2571
2572                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2573                 return_if_nok (error);
2574
2575                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2576                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2577         }
2578 }
2579
2580 static void
2581 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2582 {
2583         MONO_REQ_GC_UNSAFE_MODE;
2584
2585         GenericParamTableEntry *entry;
2586
2587         /*
2588          * The GenericParam table must be sorted according to the `owner' field.
2589          * We need to do this sorting prior to writing the GenericParamConstraint
2590          * table, since we have to use the final GenericParam table indices there
2591          * and they must also be sorted.
2592          */
2593
2594         entry = g_new0 (GenericParamTableEntry, 1);
2595         entry->owner = owner;
2596         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2597         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2598         entry->gparam = gparam;
2599         
2600         g_ptr_array_add (assembly->gen_params, entry);
2601 }
2602
2603 static gboolean
2604 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2605 {
2606         MONO_REQ_GC_UNSAFE_MODE;
2607
2608         MonoDynamicTable *table;
2609         MonoGenericParam *param;
2610         guint32 *values;
2611         guint32 table_idx;
2612
2613         mono_error_init (error);
2614
2615         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2616         table_idx = table->next_idx ++;
2617         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2618
2619         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2620         return_val_if_nok (error, FALSE);
2621
2622         param = gparam_type->data.generic_param;
2623
2624         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2625         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2626         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2627         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2628
2629         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2630                 return FALSE;
2631
2632         encode_constraints (entry->gparam, table_idx, assembly, error);
2633         return_val_if_nok (error, FALSE);
2634
2635         return TRUE;
2636 }
2637
2638 static guint32
2639 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2640 {
2641         MONO_REQ_GC_UNSAFE_MODE;
2642
2643         MonoDynamicTable *table;
2644         guint32 token;
2645         guint32 *values;
2646         guint32 cols [MONO_ASSEMBLY_SIZE];
2647         const char *pubkey;
2648         guint32 publen;
2649
2650         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2651                 return token;
2652
2653         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2654                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2655                 token = table->next_idx ++;
2656                 table->rows ++;
2657                 alloc_table (table, table->rows);
2658                 values = table->values + token * MONO_MODULEREF_SIZE;
2659                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2660
2661                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2662                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2663                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2664
2665                 return token;
2666         }
2667         
2668         if (assembly_is_dynamic (image->assembly))
2669                 /* FIXME: */
2670                 memset (cols, 0, sizeof (cols));
2671         else {
2672                 /* image->assembly->image is the manifest module */
2673                 image = image->assembly->image;
2674                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2675         }
2676
2677         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2678         token = table->next_idx ++;
2679         table->rows ++;
2680         alloc_table (table, table->rows);
2681         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2682         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2683         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2684         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2685         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2686         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2687         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2688         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2689         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2690
2691         if (strcmp ("", image->assembly->aname.culture)) {
2692                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2693                                 image->assembly->aname.culture);
2694         }
2695
2696         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2697                 guchar pubtoken [9];
2698                 pubtoken [0] = 8;
2699                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2701         } else {
2702                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2703         }
2704         token <<= MONO_RESOLUTION_SCOPE_BITS;
2705         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2706         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2707         return token;
2708 }
2709
2710 static guint32
2711 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2712 {
2713         MONO_REQ_GC_NEUTRAL_MODE;
2714
2715         MonoDynamicTable *table;
2716         guint32 *values;
2717         guint32 token;
2718         SigBuffer buf;
2719
2720         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2721                 return token;
2722
2723         sigbuffer_init (&buf, 32);
2724         switch (type->type) {
2725         case MONO_TYPE_FNPTR:
2726         case MONO_TYPE_PTR:
2727         case MONO_TYPE_SZARRAY:
2728         case MONO_TYPE_ARRAY:
2729         case MONO_TYPE_VAR:
2730         case MONO_TYPE_MVAR:
2731         case MONO_TYPE_GENERICINST:
2732                 encode_type (assembly, type, &buf);
2733                 break;
2734         case MONO_TYPE_CLASS:
2735         case MONO_TYPE_VALUETYPE: {
2736                 MonoClass *k = mono_class_from_mono_type (type);
2737                 if (!k || !k->generic_container) {
2738                         sigbuffer_free (&buf);
2739                         return 0;
2740                 }
2741                 encode_type (assembly, type, &buf);
2742                 break;
2743         }
2744         default:
2745                 sigbuffer_free (&buf);
2746                 return 0;
2747         }
2748
2749         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2750         if (assembly->save) {
2751                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2752                 alloc_table (table, table->rows + 1);
2753                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2754                 values [MONO_TYPESPEC_SIGNATURE] = token;
2755         }
2756         sigbuffer_free (&buf);
2757
2758         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2759         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2760         table->next_idx ++;
2761         return token;
2762 }
2763
2764 static guint32
2765 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2766 {
2767         MONO_REQ_GC_UNSAFE_MODE;
2768
2769         MonoDynamicTable *table;
2770         guint32 *values;
2771         guint32 token, scope, enclosing;
2772         MonoClass *klass;
2773
2774         /* if the type requires a typespec, we must try that first*/
2775         if (try_typespec && (token = create_typespec (assembly, type)))
2776                 return token;
2777         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2778         if (token)
2779                 return token;
2780         klass = mono_class_from_mono_type (type);
2781         if (!klass)
2782                 klass = mono_class_from_mono_type (type);
2783
2784         /*
2785          * If it's in the same module and not a generic type parameter:
2786          */
2787         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2788                         (type->type != MONO_TYPE_MVAR)) {
2789                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2790                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2791                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2792                 return token;
2793         }
2794
2795         if (klass->nested_in) {
2796                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2797                 /* get the typeref idx of the enclosing type */
2798                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2799                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2800         } else {
2801                 scope = resolution_scope_from_image (assembly, klass->image);
2802         }
2803         table = &assembly->tables [MONO_TABLE_TYPEREF];
2804         if (assembly->save) {
2805                 alloc_table (table, table->rows + 1);
2806                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2807                 values [MONO_TYPEREF_SCOPE] = scope;
2808                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2809                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2810         }
2811         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2812         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2813         table->next_idx ++;
2814         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2815         return token;
2816 }
2817
2818 /*
2819  * Despite the name, we handle also TypeSpec (with the above helper).
2820  */
2821 static guint32
2822 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2823 {
2824         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2825 }
2826
2827 #ifndef DISABLE_REFLECTION_EMIT
2828 static guint32
2829 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2830 {
2831         MONO_REQ_GC_NEUTRAL_MODE;
2832
2833         MonoDynamicTable *table;
2834         guint32 *values;
2835         guint32 token, pclass;
2836
2837         switch (parent & MONO_TYPEDEFORREF_MASK) {
2838         case MONO_TYPEDEFORREF_TYPEREF:
2839                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2840                 break;
2841         case MONO_TYPEDEFORREF_TYPESPEC:
2842                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2843                 break;
2844         case MONO_TYPEDEFORREF_TYPEDEF:
2845                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2846                 break;
2847         default:
2848                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2849                 return 0;
2850         }
2851         /* extract the index */
2852         parent >>= MONO_TYPEDEFORREF_BITS;
2853
2854         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2855
2856         if (assembly->save) {
2857                 alloc_table (table, table->rows + 1);
2858                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2859                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2860                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2861                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2862         }
2863
2864         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2865         table->next_idx ++;
2866
2867         return token;
2868 }
2869
2870 /*
2871  * Insert a memberef row into the metadata: the token that point to the memberref
2872  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2873  * mono_image_get_fieldref_token()).
2874  * The sig param is an index to an already built signature.
2875  */
2876 static guint32
2877 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2878 {
2879         MONO_REQ_GC_NEUTRAL_MODE;
2880
2881         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2882         return mono_image_add_memberef_row (assembly, parent, name, sig);
2883 }
2884
2885
2886 static guint32
2887 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2888 {
2889         MONO_REQ_GC_NEUTRAL_MODE;
2890
2891         guint32 token;
2892         MonoMethodSignature *sig;
2893         
2894         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2895
2896         if (create_typespec) {
2897                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2898                 if (token)
2899                         return token;
2900         } 
2901
2902         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2903         if (token && !create_typespec)
2904                 return token;
2905
2906         g_assert (!method->is_inflated);
2907         if (!token) {
2908                 /*
2909                  * A methodref signature can't contain an unmanaged calling convention.
2910                  */
2911                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2912                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2913                         sig->call_convention = MONO_CALL_DEFAULT;
2914                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2915                         method->name,  method_encode_signature (assembly, sig));
2916                 g_free (sig);
2917                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2918         }
2919
2920         if (create_typespec) {
2921                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2922                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2923                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2924
2925                 if (assembly->save) {
2926                         guint32 *values;
2927
2928                         alloc_table (table, table->rows + 1);
2929                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2930                         values [MONO_METHODSPEC_METHOD] = token;
2931                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2932                 }
2933
2934                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2935                 table->next_idx ++;
2936                 /*methodspec and memberef tokens are diferent, */
2937                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2938                 return token;
2939         }
2940         return token;
2941 }
2942
2943 static guint32
2944 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2945 {
2946         guint32 token, parent, sig;
2947         ReflectionMethodBuilder rmb;
2948         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2949         
2950         mono_error_init (error);
2951         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2952         if (token)
2953                 return token;
2954
2955         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2956                 return 0;
2957
2958         /*
2959          * A methodref signature can't contain an unmanaged calling convention.
2960          * Since some flags are encoded as part of call_conv, we need to check against it.
2961         */
2962         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2963                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2964
2965         sig = method_builder_encode_signature (assembly, &rmb, error);
2966         return_val_if_nok (error, 0);
2967
2968         if (tb->generic_params) {
2969                 parent = create_generic_typespec (assembly, tb, error);
2970                 return_val_if_nok (error, 0);
2971         } else {
2972                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2973                 return_val_if_nok (error, 0);
2974
2975                 parent = mono_image_typedef_or_ref (assembly, t);
2976         }
2977
2978         char *name = mono_string_to_utf8 (method->name);
2979
2980         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2981         g_free (name);
2982
2983         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2984
2985         return token;
2986 }
2987
2988 static guint32
2989 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2990                                      const gchar *name, guint32 sig)
2991 {
2992         MonoDynamicTable *table;
2993         guint32 token;
2994         guint32 *values;
2995         
2996         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2997
2998         if (assembly->save) {
2999                 alloc_table (table, table->rows + 1);
3000                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3001                 values [MONO_MEMBERREF_CLASS] = original;
3002                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3003                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3004         }
3005
3006         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3007         table->next_idx ++;
3008
3009         return token;
3010 }
3011
3012 static guint32
3013 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3014 {
3015         SigBuffer buf;
3016         int i;
3017         guint32 nparams = mono_array_length (mb->generic_params);
3018         guint32 idx;
3019
3020         if (!assembly->save)
3021                 return 0;
3022
3023         sigbuffer_init (&buf, 32);
3024
3025         sigbuffer_add_value (&buf, 0xa);
3026         sigbuffer_add_value (&buf, nparams);
3027
3028         for (i = 0; i < nparams; i++) {
3029                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3030                 sigbuffer_add_value (&buf, i);
3031         }
3032
3033         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034         sigbuffer_free (&buf);
3035         return idx;
3036 }
3037
3038 static guint32
3039 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3040 {
3041         MonoDynamicTable *table;
3042         guint32 *values;
3043         guint32 token, mtoken = 0;
3044
3045         mono_error_init (error);
3046         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3047         if (token)
3048                 return token;
3049
3050         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3051
3052         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3053         if (!mono_error_ok (error))
3054                 return 0;
3055
3056         switch (mono_metadata_token_table (mtoken)) {
3057         case MONO_TABLE_MEMBERREF:
3058                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3059                 break;
3060         case MONO_TABLE_METHOD:
3061                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3062                 break;
3063         default:
3064                 g_assert_not_reached ();
3065         }
3066
3067         if (assembly->save) {
3068                 alloc_table (table, table->rows + 1);
3069                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3070                 values [MONO_METHODSPEC_METHOD] = mtoken;
3071                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3072         }
3073
3074         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3075         table->next_idx ++;
3076
3077         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3078         return token;
3079 }
3080
3081 static guint32
3082 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3083 {
3084         guint32 token;
3085
3086         mono_error_init (error);
3087
3088         if (mb->generic_params && create_methodspec) 
3089                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3090
3091         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3092         if (token)
3093                 return token;
3094
3095         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3096         if (!mono_error_ok (error))
3097                 return 0;
3098         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3099         return token;
3100 }
3101
3102 static guint32
3103 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3104 {
3105         guint32 token, parent, sig;
3106         ReflectionMethodBuilder rmb;
3107         char *name;
3108         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3109         
3110         mono_error_init (error);
3111         
3112         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3113         if (token)
3114                 return token;
3115
3116         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3117                 return 0;
3118
3119         if (tb->generic_params) {
3120                 parent = create_generic_typespec (assembly, tb, error);
3121                 return_val_if_nok (error, 0);
3122         } else {
3123                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3124                 return_val_if_nok (error, 0);
3125                 parent = mono_image_typedef_or_ref (assembly, type);
3126         }
3127         
3128         name = mono_string_to_utf8 (rmb.name);
3129         sig = method_builder_encode_signature (assembly, &rmb, error);
3130         return_val_if_nok (error, 0);
3131
3132         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3133
3134         g_free (name);
3135         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3136         return token;
3137 }
3138 #endif
3139
3140 static gboolean
3141 is_field_on_inst (MonoClassField *field)
3142 {
3143         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3144 }
3145
3146 /*
3147  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3148  */
3149 static MonoType*
3150 get_field_on_inst_generic_type (MonoClassField *field)
3151 {
3152         MonoClass *klass, *gtd;
3153         MonoDynamicGenericClass *dgclass;
3154         int field_index;
3155
3156         g_assert (is_field_on_inst (field));
3157
3158         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3159
3160         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3161                 field_index = field - dgclass->fields;
3162                 return dgclass->field_generic_types [field_index];              
3163         }
3164
3165         klass = field->parent;
3166         gtd = klass->generic_class->container_class;
3167
3168         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3169                 field_index = field - klass->fields;
3170                 return gtd->fields [field_index].type;
3171         }
3172
3173         g_assert_not_reached ();
3174         return 0;
3175 }
3176
3177 #ifndef DISABLE_REFLECTION_EMIT
3178 static guint32
3179 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3180 {
3181         MonoType *type;
3182         guint32 token;
3183
3184         g_assert (field);
3185         g_assert (field->parent);
3186
3187         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3188         if (token)
3189                 return token;
3190
3191         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3192                 int index = field - field->parent->fields;
3193                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3194         } else {
3195                 if (is_field_on_inst (field))
3196                         type = get_field_on_inst_generic_type (field);
3197                 else
3198                         type = mono_field_get_type (field);
3199         }
3200         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3201                                                                                         mono_field_get_name (field),
3202                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3203         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3204         return token;
3205 }
3206
3207 static guint32
3208 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3209 {
3210         guint32 token;
3211         MonoClass *klass;
3212         MonoGenericClass *gclass;
3213         MonoType *type;
3214         char *name;
3215
3216         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3217         if (token)
3218                 return token;
3219         if (is_sre_field_builder (mono_object_class (f->fb))) {
3220                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3221                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3222                 return_val_if_nok (error, 0);
3223                 klass = mono_class_from_mono_type (type);
3224                 gclass = type->data.generic_class;
3225                 g_assert (gclass->is_dynamic);
3226
3227                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3228                 return_val_if_nok (error, 0);
3229                 name = mono_string_to_utf8 (fb->name);
3230                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3231                 g_free (name);          
3232         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3233                 guint32 sig;
3234                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3235
3236                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3237                 return_val_if_nok (error, 0);
3238                 klass = mono_class_from_mono_type (type);
3239
3240                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3241                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3242         } else {
3243                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3244                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3245         }
3246
3247         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3248         return token;
3249 }
3250
3251 static guint32
3252 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3253 {
3254         guint32 sig, token;
3255         MonoClass *klass;
3256         MonoGenericClass *gclass;
3257         MonoType *type;
3258
3259         mono_error_init (error);
3260
3261         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3262
3263         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3264         if (token)
3265                 return token;
3266
3267         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3268                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3269                 ReflectionMethodBuilder rmb;
3270                 char *name;
3271
3272                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3273                 return_val_if_nok (error, 0);
3274                 klass = mono_class_from_mono_type (type);
3275
3276                 gclass = type->data.generic_class;
3277                 g_assert (gclass->is_dynamic);
3278
3279                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3280                         return 0;
3281
3282                 sig = method_builder_encode_signature (assembly, &rmb, error);
3283                 return_val_if_nok (error, 0);
3284
3285                 name = mono_string_to_utf8 (rmb.name);
3286
3287                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3288                 g_free (name);
3289         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3290                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3291
3292                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3293                 return_val_if_nok (error, 0);
3294                 klass = mono_class_from_mono_type (type);
3295
3296                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3297                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3298         } else {
3299                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3300                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3301         }
3302
3303
3304         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3305         return token;
3306 }
3307
3308 static MonoMethod*
3309 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3310 {
3311         MonoClass *klass;
3312         MonoGenericContext tmp_context;
3313         MonoType **type_argv;
3314         MonoGenericInst *ginst;
3315         MonoMethod *method, *inflated;
3316         int count, i;
3317
3318         mono_error_init (error);
3319
3320         init_type_builder_generics ((MonoObject*)m->inst);
3321
3322         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3323         return_val_if_nok (error, NULL);
3324
3325         klass = method->klass;
3326
3327         if (m->method_args == NULL)
3328                 return method;
3329
3330         if (method->is_inflated)
3331                 method = ((MonoMethodInflated *) method)->declaring;
3332
3333         count = mono_array_length (m->method_args);
3334
3335         type_argv = g_new0 (MonoType *, count);
3336         for (i = 0; i < count; i++) {
3337                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3338                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3339                 return_val_if_nok (error, NULL);
3340         }
3341         ginst = mono_metadata_get_generic_inst (count, type_argv);
3342         g_free (type_argv);
3343
3344         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3345         tmp_context.method_inst = ginst;
3346
3347         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3348         mono_error_assert_ok (error);
3349         return inflated;
3350 }
3351
3352 static guint32
3353 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3354 {
3355         guint32 sig, token = 0;
3356         MonoType *type;
3357         MonoClass *klass;
3358
3359         mono_error_init (error);
3360
3361         if (m->method_args) {
3362                 MonoMethod *inflated;
3363
3364                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3365                 return_val_if_nok (error, 0);
3366
3367                 if (create_methodspec)
3368                         token = mono_image_get_methodspec_token (assembly, inflated);
3369                 else
3370                         token = mono_image_get_inflated_method_token (assembly, inflated);
3371                 return token;
3372         }
3373
3374         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3375         if (token)
3376                 return token;
3377
3378         if (is_sre_method_builder (mono_object_class (m->mb))) {
3379                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3380                 MonoGenericClass *gclass;
3381                 ReflectionMethodBuilder rmb;
3382                 char *name;
3383
3384                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3385                 return_val_if_nok (error, 0);
3386                 klass = mono_class_from_mono_type (type);
3387                 gclass = type->data.generic_class;
3388                 g_assert (gclass->is_dynamic);
3389
3390                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3391                         return 0;
3392
3393                 sig = method_builder_encode_signature (assembly, &rmb, error);
3394                 return_val_if_nok (error, 0);
3395
3396                 name = mono_string_to_utf8 (rmb.name);
3397
3398                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3399                 g_free (name);          
3400         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3401                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3402
3403                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3404                 return_val_if_nok (error, 0);
3405                 klass = mono_class_from_mono_type (type);
3406
3407                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3408                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3409         } else {
3410                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3411                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3412         }
3413
3414         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3415         return token;
3416 }
3417
3418 static guint32
3419 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3420 {
3421         SigBuffer buf;
3422         int i;
3423         guint32 nparams = context->method_inst->type_argc;
3424         guint32 idx;
3425
3426         if (!assembly->save)
3427                 return 0;
3428
3429         sigbuffer_init (&buf, 32);
3430         /*
3431          * FIXME: vararg, explicit_this, differenc call_conv values...
3432          */
3433         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3434         sigbuffer_add_value (&buf, nparams);
3435
3436         for (i = 0; i < nparams; i++)
3437                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3438
3439         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3440         sigbuffer_free (&buf);
3441         return idx;
3442 }
3443
3444 static guint32
3445 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3446 {
3447         MonoDynamicTable *table;
3448         guint32 *values;
3449         guint32 token, mtoken = 0, sig;
3450         MonoMethodInflated *imethod;
3451         MonoMethod *declaring;
3452
3453         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3454
3455         g_assert (method->is_inflated);
3456         imethod = (MonoMethodInflated *) method;
3457         declaring = imethod->declaring;
3458
3459         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3460         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3461
3462         if (!mono_method_signature (declaring)->generic_param_count)
3463                 return mtoken;
3464
3465         switch (mono_metadata_token_table (mtoken)) {
3466         case MONO_TABLE_MEMBERREF:
3467                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3468                 break;
3469         case MONO_TABLE_METHOD:
3470                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3471                 break;
3472         default:
3473                 g_assert_not_reached ();
3474         }
3475
3476         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3477
3478         if (assembly->save) {
3479                 alloc_table (table, table->rows + 1);
3480                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3481                 values [MONO_METHODSPEC_METHOD] = mtoken;
3482                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3483         }
3484
3485         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3486         table->next_idx ++;
3487
3488         return token;
3489 }
3490
3491 static guint32
3492 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3493 {
3494         MonoMethodInflated *imethod;
3495         guint32 token;
3496         
3497         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3498         if (token)
3499                 return token;
3500
3501         g_assert (method->is_inflated);
3502         imethod = (MonoMethodInflated *) method;
3503
3504         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3505                 token = method_encode_methodspec (assembly, method);
3506         } else {
3507                 guint32 sig = method_encode_signature (
3508                         assembly, mono_method_signature (imethod->declaring));
3509                 token = mono_image_get_memberref_token (
3510                         assembly, &method->klass->byval_arg, method->name, sig);
3511         }
3512
3513         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3514         return token;
3515 }
3516
3517 static guint32
3518 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3519 {
3520         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3521         guint32 sig, token;
3522
3523         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3524         token = mono_image_get_memberref_token (
3525                 assembly, &m->klass->byval_arg, m->name, sig);
3526
3527         return token;
3528 }
3529
3530 static guint32
3531 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3532 {
3533         MonoDynamicTable *table;
3534         MonoClass *klass;
3535         MonoType *type;
3536         guint32 *values;
3537         guint32 token;
3538         SigBuffer buf;
3539         int count, i;
3540
3541         /*
3542          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3543          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3544          * Because of this, we must not insert it into the `typeref' hash table.
3545          */
3546         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3547         return_val_if_nok (error, 0);
3548         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3549         if (token)
3550                 return token;
3551
3552         sigbuffer_init (&buf, 32);
3553
3554         g_assert (tb->generic_params);
3555         klass = mono_class_from_mono_type (type);
3556
3557         if (tb->generic_container)
3558                 mono_reflection_create_generic_class (tb);
3559
3560         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3561         g_assert (klass->generic_container);
3562         sigbuffer_add_value (&buf, klass->byval_arg.type);
3563         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3564
3565         count = mono_array_length (tb->generic_params);
3566         sigbuffer_add_value (&buf, count);
3567         for (i = 0; i < count; i++) {
3568                 MonoReflectionGenericParam *gparam;
3569
3570                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3571                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3572                 if (!is_ok (error))
3573                         goto fail;
3574
3575                 encode_type (assembly, gparam_type, &buf);
3576         }
3577
3578         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3579
3580         if (assembly->save) {
3581                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3582                 alloc_table (table, table->rows + 1);
3583                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3584                 values [MONO_TYPESPEC_SIGNATURE] = token;
3585         }
3586         sigbuffer_free (&buf);
3587
3588         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3589         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3590         table->next_idx ++;
3591         return token;
3592 fail:
3593         sigbuffer_free (&buf);
3594         return 0;
3595 }
3596
3597 /*
3598  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3599  */
3600 static MonoType*
3601 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3602 {
3603         int i, count, len, pos;
3604         MonoType *t;
3605
3606         mono_error_init (error);
3607
3608         count = 0;
3609         if (modreq)
3610                 count += mono_array_length (modreq);
3611         if (modopt)
3612                 count += mono_array_length (modopt);
3613
3614         if (count == 0)
3615                 return mono_metadata_type_dup (NULL, type);
3616
3617         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3618         t = (MonoType *)g_malloc (len);
3619         memcpy (t, type, MONO_SIZEOF_TYPE);
3620
3621         t->num_mods = count;
3622         pos = 0;
3623         if (modreq) {
3624                 for (i = 0; i < mono_array_length (modreq); ++i) {
3625                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3626                         if (!is_ok (error))
3627                                 goto fail;
3628                         t->modifiers [pos].required = 1;
3629                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3630                         pos ++;
3631                 }
3632         }
3633         if (modopt) {
3634                 for (i = 0; i < mono_array_length (modopt); ++i) {
3635                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3636                         if (!is_ok (error))
3637                                 goto fail;
3638                         t->modifiers [pos].required = 0;
3639                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3640                         pos ++;
3641                 }
3642         }
3643
3644         return t;
3645 fail:
3646         g_free (t);
3647         return NULL;
3648 }
3649
3650 static void
3651 init_type_builder_generics (MonoObject *type)
3652 {
3653         MonoReflectionTypeBuilder *tb;
3654
3655         if (!is_sre_type_builder(mono_object_class (type)))
3656                 return;
3657         tb = (MonoReflectionTypeBuilder *)type;
3658
3659         if (tb && tb->generic_container)
3660                 mono_reflection_create_generic_class (tb);
3661 }
3662
3663 static guint32
3664 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3665 {
3666         MonoDynamicTable *table;
3667         MonoType *custom = NULL, *type;
3668         guint32 *values;
3669         guint32 token, pclass, parent, sig;
3670         gchar *name;
3671
3672         mono_error_init (error);
3673
3674         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3675         if (token)
3676                 return token;
3677
3678         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3679         return_val_if_nok (error, 0);
3680         /* FIXME: is this call necessary? */
3681         mono_class_from_mono_type (typeb);
3682
3683         /*FIXME this is one more layer of ugliness due how types are created.*/
3684         init_type_builder_generics (fb->type);
3685
3686         /* fb->type does not include the custom modifiers */
3687         /* FIXME: We should do this in one place when a fieldbuilder is created */
3688         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3689         return_val_if_nok (error, 0);
3690
3691         if (fb->modreq || fb->modopt) {
3692                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3693                 return_val_if_nok (error, 0);
3694         }
3695
3696         sig = fieldref_encode_signature (assembly, NULL, type);
3697         g_free (custom);
3698
3699         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3700         return_val_if_nok (error, 0);
3701         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3702         
3703         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3704         parent >>= MONO_TYPEDEFORREF_BITS;
3705
3706         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3707
3708         name = mono_string_to_utf8 (fb->name);
3709
3710         if (assembly->save) {
3711                 alloc_table (table, table->rows + 1);
3712                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3713                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3714                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3715                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3716         }
3717
3718         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3719         table->next_idx ++;
3720         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3721         g_free (name);
3722         return token;
3723 }
3724
3725 static guint32
3726 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3727 {
3728         SigBuffer buf;
3729         guint32 nargs;
3730         guint32 i, idx;
3731
3732         mono_error_init (error);
3733
3734         if (!assembly->save)
3735                 return 0;
3736
3737         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3738         g_assert (helper->type == 2);
3739
3740         if (helper->arguments)
3741                 nargs = mono_array_length (helper->arguments);
3742         else
3743                 nargs = 0;
3744
3745         sigbuffer_init (&buf, 32);
3746
3747         /* Encode calling convention */
3748         /* Change Any to Standard */
3749         if ((helper->call_conv & 0x03) == 0x03)
3750                 helper->call_conv = 0x01;
3751         /* explicit_this implies has_this */
3752         if (helper->call_conv & 0x40)
3753                 helper->call_conv &= 0x20;
3754
3755         if (helper->call_conv == 0) { /* Unmanaged */
3756                 idx = helper->unmanaged_call_conv - 1;
3757         } else {
3758                 /* Managed */
3759                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3760                 if (helper->call_conv & 0x02) /* varargs */
3761                         idx += 0x05;
3762         }
3763
3764         sigbuffer_add_byte (&buf, idx);
3765         sigbuffer_add_value (&buf, nargs);
3766         encode_reflection_type (assembly, helper->return_type, &buf, error);
3767         if (!is_ok (error))
3768                 goto fail;
3769         for (i = 0; i < nargs; ++i) {
3770                 MonoArray *modreqs = NULL;
3771                 MonoArray *modopts = NULL;
3772                 MonoReflectionType *pt;
3773
3774                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3775                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3776                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3777                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3778
3779                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3780                 if (!is_ok (error))
3781                         goto fail;
3782                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3783                 encode_reflection_type (assembly, pt, &buf, error);
3784                 if (!is_ok (error))
3785                         goto fail;
3786         }
3787         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3788         sigbuffer_free (&buf);
3789
3790         return idx;
3791 fail:
3792         sigbuffer_free (&buf);
3793         return 0;
3794 }
3795
3796 static guint32 
3797 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3798 {
3799         guint32 idx;
3800         MonoDynamicTable *table;
3801         guint32 *values;
3802
3803         mono_error_init (error);
3804
3805         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3806         idx = table->next_idx ++;
3807         table->rows ++;
3808         alloc_table (table, table->rows);
3809         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3810
3811         values [MONO_STAND_ALONE_SIGNATURE] =
3812                 mono_reflection_encode_sighelper (assembly, helper, error);
3813         return_val_if_nok (error, 0);
3814         
3815         return idx;
3816 }
3817
3818 static int
3819 reflection_cc_to_file (int call_conv) {
3820         switch (call_conv & 0x3) {
3821         case 0:
3822         case 1: return MONO_CALL_DEFAULT;
3823         case 2: return MONO_CALL_VARARG;
3824         default:
3825                 g_assert_not_reached ();
3826         }
3827         return 0;
3828 }
3829 #endif /* !DISABLE_REFLECTION_EMIT */
3830
3831 typedef struct {
3832         MonoType *parent;
3833         MonoMethodSignature *sig;
3834         char *name;
3835         guint32 token;
3836 } ArrayMethod;
3837
3838 #ifndef DISABLE_REFLECTION_EMIT
3839 static guint32
3840 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3841 {
3842         guint32 nparams, i;
3843         GList *tmp;
3844         char *name = NULL;
3845         MonoMethodSignature *sig;
3846         ArrayMethod *am = NULL;
3847         MonoType *mtype;
3848
3849         mono_error_init (error);
3850
3851         nparams = mono_array_length (m->parameters);
3852         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3853         sig->hasthis = 1;
3854         sig->sentinelpos = -1;
3855         sig->call_convention = reflection_cc_to_file (m->call_conv);
3856         sig->param_count = nparams;
3857         if (m->ret) {
3858                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3859                 if (!is_ok (error))
3860                         goto fail;
3861         } else
3862                 sig->ret = &mono_defaults.void_class->byval_arg;
3863
3864         mtype = mono_reflection_type_get_handle (m->parent, error);
3865         if (!is_ok (error))
3866                 goto fail;
3867
3868         for (i = 0; i < nparams; ++i) {
3869                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3870                 if (!is_ok (error))
3871                         goto fail;
3872         }
3873
3874         name = mono_string_to_utf8 (m->name);
3875         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3876                 am = (ArrayMethod *)tmp->data;
3877                 if (strcmp (name, am->name) == 0 && 
3878                                 mono_metadata_type_equal (am->parent, mtype) &&
3879                                 mono_metadata_signature_equal (am->sig, sig)) {
3880                         g_free (name);
3881                         g_free (sig);
3882                         m->table_idx = am->token & 0xffffff;
3883                         return am->token;
3884                 }
3885         }
3886         am = g_new0 (ArrayMethod, 1);
3887         am->name = name;
3888         am->sig = sig;
3889         am->parent = mtype;
3890         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3891                 method_encode_signature (assembly, sig));
3892         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3893         m->table_idx = am->token & 0xffffff;
3894         return am->token;
3895 fail:
3896         g_free (am);
3897         g_free (name);
3898         g_free (sig);
3899         return 0;
3900
3901 }
3902
3903 /*
3904  * Insert into the metadata tables all the info about the TypeBuilder tb.
3905  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3906  */
3907 static gboolean
3908 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3909 {
3910         MonoDynamicTable *table;
3911         guint *values;
3912         int i, is_object = 0, is_system = 0;
3913         char *n;
3914
3915         mono_error_init (error);
3916
3917         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3918         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3919         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3920         n = mono_string_to_utf8 (tb->name);
3921         if (strcmp (n, "Object") == 0)
3922                 is_object++;
3923         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3924         g_free (n);
3925         n = mono_string_to_utf8 (tb->nspace);
3926         if (strcmp (n, "System") == 0)
3927                 is_system++;
3928         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3929         g_free (n);
3930         if (tb->parent && !(is_system && is_object) && 
3931                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3932                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3933                 return_val_if_nok (error, FALSE);
3934                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3935         } else {
3936                 values [MONO_TYPEDEF_EXTENDS] = 0;
3937         }
3938         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3939         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3940
3941         /*
3942          * if we have explicitlayout or sequentiallayouts, output data in the
3943          * ClassLayout table.
3944          */
3945         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3946                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3947                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3948                 table->rows++;
3949                 alloc_table (table, table->rows);
3950                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3951                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3952                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3953                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3954         }
3955
3956         /* handle interfaces */
3957         if (tb->interfaces) {
3958                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3959                 i = table->rows;
3960                 table->rows += mono_array_length (tb->interfaces);
3961                 alloc_table (table, table->rows);
3962                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3963                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3964                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3965                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3966                         return_val_if_nok (error, FALSE);
3967                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3968                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3969                         values += MONO_INTERFACEIMPL_SIZE;
3970                 }
3971         }
3972
3973         /* handle fields */
3974         if (tb->fields) {
3975                 table = &assembly->tables [MONO_TABLE_FIELD];
3976                 table->rows += tb->num_fields;
3977                 alloc_table (table, table->rows);
3978                 for (i = 0; i < tb->num_fields; ++i) {
3979                         mono_image_get_field_info (
3980                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3981                         return_val_if_nok (error, FALSE);
3982                 }
3983         }
3984
3985         /* handle constructors */
3986         if (tb->ctors) {
3987                 table = &assembly->tables [MONO_TABLE_METHOD];
3988                 table->rows += mono_array_length (tb->ctors);
3989                 alloc_table (table, table->rows);
3990                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3991                         if (!mono_image_get_ctor_info (domain,
3992                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3993                                                        assembly, error))
3994                                 return FALSE;
3995                 }
3996         }
3997
3998         /* handle methods */
3999         if (tb->methods) {
4000                 table = &assembly->tables [MONO_TABLE_METHOD];
4001                 table->rows += tb->num_methods;
4002                 alloc_table (table, table->rows);
4003                 for (i = 0; i < tb->num_methods; ++i) {
4004                         if (!mono_image_get_method_info (
4005                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4006                                 return FALSE;
4007                 }
4008         }
4009
4010         /* Do the same with properties etc.. */
4011         if (tb->events && mono_array_length (tb->events)) {
4012                 table = &assembly->tables [MONO_TABLE_EVENT];
4013                 table->rows += mono_array_length (tb->events);
4014                 alloc_table (table, table->rows);
4015                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4016                 table->rows ++;
4017                 alloc_table (table, table->rows);
4018                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4019                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4020                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4021                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4022                         mono_image_get_event_info (
4023                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4024                         return_val_if_nok (error, FALSE);
4025                 }
4026         }
4027         if (tb->properties && mono_array_length (tb->properties)) {
4028                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4029                 table->rows += mono_array_length (tb->properties);
4030                 alloc_table (table, table->rows);
4031                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4032                 table->rows ++;
4033                 alloc_table (table, table->rows);
4034                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4035                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4036                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4037                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4038                         mono_image_get_property_info (
4039                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4040                         return_val_if_nok (error, FALSE);
4041                 }
4042         }
4043
4044         /* handle generic parameters */
4045         if (tb->generic_params) {
4046                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4047                 table->rows += mono_array_length (tb->generic_params);
4048                 alloc_table (table, table->rows);
4049                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4050                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4051
4052                         mono_image_get_generic_param_info (
4053                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4054                 }
4055         }
4056
4057         mono_image_add_decl_security (assembly, 
4058                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4059
4060         if (tb->subtypes) {
4061                 MonoDynamicTable *ntable;
4062                 
4063                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4064                 ntable->rows += mono_array_length (tb->subtypes);
4065                 alloc_table (ntable, ntable->rows);
4066                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4067
4068                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4069                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4070
4071                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4072                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4073                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4074                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4075                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4076                                 ntable->next_idx, ntable->rows);*/
4077                         values += MONO_NESTED_CLASS_SIZE;
4078                         ntable->next_idx++;
4079                 }
4080         }
4081
4082         return TRUE;
4083 }
4084 #endif
4085
4086 static void
4087 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4088 {
4089         int i;
4090
4091         mono_ptr_array_append (*types, type);
4092
4093         if (!type->subtypes)
4094                 return;
4095
4096         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4097                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4098                 collect_types (types, subtype);
4099         }
4100 }
4101
4102 static gint
4103 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4104 {
4105         if ((*type1)->table_idx < (*type2)->table_idx)
4106                 return -1;
4107         else
4108                 if ((*type1)->table_idx > (*type2)->table_idx)
4109                         return 1;
4110         else
4111                 return 0;
4112 }
4113
4114 static gboolean
4115 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4116         int i;
4117
4118         mono_error_init (error);
4119         if (!pinfo)
4120                 return TRUE;
4121         for (i = 0; i < mono_array_length (pinfo); ++i) {
4122                 MonoReflectionParamBuilder *pb;
4123                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4124                 if (!pb)
4125                         continue;
4126                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4127                         return FALSE;
4128         }
4129
4130         return TRUE;
4131 }
4132
4133 static gboolean
4134 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4135         int i;
4136
4137         mono_error_init (error);
4138         
4139         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4140                 return FALSE;
4141         if (tb->fields) {
4142                 for (i = 0; i < tb->num_fields; ++i) {
4143                         MonoReflectionFieldBuilder* fb;
4144                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4145                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4146                                 return FALSE;
4147                 }
4148         }
4149         if (tb->events) {
4150                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4151                         MonoReflectionEventBuilder* eb;
4152                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4153                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4154                                 return FALSE;
4155                 }
4156         }
4157         if (tb->properties) {
4158                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4159                         MonoReflectionPropertyBuilder* pb;
4160                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4161                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4162                                 return FALSE;
4163                 }
4164         }
4165         if (tb->ctors) {
4166                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4167                         MonoReflectionCtorBuilder* cb;
4168                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4169                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4170                             !params_add_cattrs (assembly, cb->pinfo, error))
4171                                 return FALSE;
4172                 }
4173         }
4174
4175         if (tb->methods) {
4176                 for (i = 0; i < tb->num_methods; ++i) {
4177                         MonoReflectionMethodBuilder* mb;
4178                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4179                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4180                             !params_add_cattrs (assembly, mb->pinfo, error))
4181                                 return FALSE;
4182                 }
4183         }
4184
4185         if (tb->subtypes) {
4186                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4187                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4188                                 return FALSE;
4189                 }
4190         }
4191
4192         return TRUE;
4193 }
4194
4195 static gboolean
4196 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4197 {
4198         int i;
4199         
4200         mono_error_init (error);
4201
4202         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4203                 return FALSE;
4204
4205         if (moduleb->global_methods) {
4206                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4207                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4208                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4209                             !params_add_cattrs (assembly, mb->pinfo, error))
4210                                 return FALSE;
4211                 }
4212         }
4213
4214         if (moduleb->global_fields) {
4215                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4216                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4217                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4218                                 return FALSE;
4219                 }
4220         }
4221         
4222         if (moduleb->types) {
4223                 for (i = 0; i < moduleb->num_types; ++i) {
4224                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4225                                 return FALSE;
4226                 }
4227         }
4228
4229         return TRUE;
4230 }
4231
4232 static void
4233 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4234 {
4235         MonoDynamicTable *table;
4236         guint32 *values;
4237         char blob_size [6];
4238         guchar hash [20];
4239         char *b = blob_size;
4240         char *dir, *path;
4241
4242         table = &assembly->tables [MONO_TABLE_FILE];
4243         table->rows++;
4244         alloc_table (table, table->rows);
4245         values = table->values + table->next_idx * MONO_FILE_SIZE;
4246         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4247         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4248         if (image_is_dynamic (module->image)) {
4249                 /* This depends on the fact that the main module is emitted last */
4250                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4251                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4252         } else {
4253                 dir = NULL;
4254                 path = g_strdup (module->image->name);
4255         }
4256         mono_sha1_get_digest_from_file (path, hash);
4257         g_free (dir);
4258         g_free (path);
4259         mono_metadata_encode_value (20, b, &b);
4260         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4261         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4262         table->next_idx ++;
4263 }
4264
4265 static void
4266 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4267 {
4268         MonoDynamicTable *table;
4269         int i;
4270
4271         table = &assembly->tables [MONO_TABLE_MODULE];
4272         mb->table_idx = table->next_idx ++;
4273         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4274         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4275         i /= 16;
4276         ++i;
4277         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4278         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4279         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4280         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4281 }
4282
4283 static guint32
4284 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4285         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4286 {
4287         MonoDynamicTable *table;
4288         guint32 *values;
4289         guint32 visib, res;
4290
4291         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4292         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4293                 return 0;
4294
4295         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4296         table->rows++;
4297         alloc_table (table, table->rows);
4298         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4299
4300         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4301         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4302         if (klass->nested_in)
4303                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4304         else
4305                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4306         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4307         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4308
4309         res = table->next_idx;
4310
4311         table->next_idx ++;
4312
4313         /* Emit nested types */
4314         if (klass->ext && klass->ext->nested_classes) {
4315                 GList *tmp;
4316
4317                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4318                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4319         }
4320
4321         return res;
4322 }
4323
4324 static void
4325 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4326                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4327                               MonoError *error)
4328 {
4329         MonoClass *klass;
4330         guint32 idx, i;
4331
4332         mono_error_init (error);
4333
4334         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4335         return_if_nok (error);
4336
4337         klass = mono_class_from_mono_type (t);
4338
4339         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4340
4341         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4342                                                                                                    parent_index, assembly);
4343
4344         /* 
4345          * Emit nested types
4346          * We need to do this ourselves since klass->nested_classes is not set up.
4347          */
4348         if (tb->subtypes) {
4349                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4350                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4351                         return_if_nok (error);
4352                 }
4353         }
4354 }
4355
4356 static void
4357 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4358         guint32 module_index, MonoDynamicImage *assembly)
4359 {
4360         MonoImage *image = module->image;
4361         MonoTableInfo  *t;
4362         guint32 i;
4363
4364         t = &image->tables [MONO_TABLE_TYPEDEF];
4365
4366         for (i = 0; i < t->rows; ++i) {
4367                 MonoError error;
4368                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4369                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4370
4371                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4372                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4373         }
4374 }
4375
4376 static void
4377 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4378 {
4379         MonoDynamicTable *table;
4380         guint32 *values;
4381         guint32 scope, scope_idx, impl, current_idx;
4382         gboolean forwarder = TRUE;
4383         gpointer iter = NULL;
4384         MonoClass *nested;
4385
4386         if (klass->nested_in) {
4387                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4388                 forwarder = FALSE;
4389         } else {
4390                 scope = resolution_scope_from_image (assembly, klass->image);
4391                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4392                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4393                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4394         }
4395
4396         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4397
4398         table->rows++;
4399         alloc_table (table, table->rows);
4400         current_idx = table->next_idx;
4401         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4402
4403         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4404         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4405         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4406         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4407         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4408
4409         table->next_idx++;
4410
4411         while ((nested = mono_class_get_nested_types (klass, &iter)))
4412                 add_exported_type (assemblyb, assembly, nested, current_idx);
4413 }
4414
4415 static void
4416 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4417 {
4418         MonoError error;
4419         MonoClass *klass;
4420         int i;
4421
4422         if (!assemblyb->type_forwarders)
4423                 return;
4424
4425         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4426                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4427                 MonoType *type;
4428                 if (!t)
4429                         continue;
4430
4431                 type = mono_reflection_type_get_handle (t, &error);
4432                 mono_error_assert_ok (&error);
4433                 g_assert (type);
4434
4435                 klass = mono_class_from_mono_type (type);
4436
4437                 add_exported_type (assemblyb, assembly, klass, 0);
4438         }
4439 }
4440
4441 #define align_pointer(base,p)\
4442         do {\
4443                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4444                 if (__diff & 3)\
4445                         (p) += 4 - (__diff & 3);\
4446         } while (0)
4447
4448 static int
4449 compare_constants (const void *a, const void *b)
4450 {
4451         const guint32 *a_values = (const guint32 *)a;
4452         const guint32 *b_values = (const guint32 *)b;
4453         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4454 }
4455
4456 static int
4457 compare_semantics (const void *a, const void *b)
4458 {
4459         const guint32 *a_values = (const guint32 *)a;
4460         const guint32 *b_values = (const guint32 *)b;
4461         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4462         if (assoc)
4463                 return assoc;
4464         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4465 }
4466
4467 static int
4468 compare_custom_attrs (const void *a, const void *b)
4469 {
4470         const guint32 *a_values = (const guint32 *)a;
4471         const guint32 *b_values = (const guint32 *)b;
4472
4473         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4474 }
4475
4476 static int
4477 compare_field_marshal (const void *a, const void *b)
4478 {
4479         const guint32 *a_values = (const guint32 *)a;
4480         const guint32 *b_values = (const guint32 *)b;
4481
4482         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4483 }
4484
4485 static int
4486 compare_nested (const void *a, const void *b)
4487 {
4488         const guint32 *a_values = (const guint32 *)a;
4489         const guint32 *b_values = (const guint32 *)b;
4490
4491         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4492 }
4493
4494 static int
4495 compare_genericparam (const void *a, const void *b)
4496 {
4497         MonoError error;
4498         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4499         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4500
4501         if ((*b_entry)->owner == (*a_entry)->owner) {
4502                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4503                 mono_error_assert_ok (&error);
4504                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4505                 mono_error_assert_ok (&error);
4506                 return 
4507                         mono_type_get_generic_param_num (a_type) -
4508                         mono_type_get_generic_param_num (b_type);
4509         } else
4510                 return (*a_entry)->owner - (*b_entry)->owner;
4511 }
4512
4513 static int
4514 compare_declsecurity_attrs (const void *a, const void *b)
4515 {
4516         const guint32 *a_values = (const guint32 *)a;
4517         const guint32 *b_values = (const guint32 *)b;
4518
4519         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4520 }
4521
4522 static int
4523 compare_interface_impl (const void *a, const void *b)
4524 {
4525         const guint32 *a_values = (const guint32 *)a;
4526         const guint32 *b_values = (const guint32 *)b;
4527
4528         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4529         if (klass)
4530                 return klass;
4531
4532         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4533 }
4534
4535 static void
4536 pad_heap (MonoDynamicStream *sh)
4537 {
4538         if (sh->index & 3) {
4539                 int sz = 4 - (sh->index & 3);
4540                 memset (sh->data + sh->index, 0, sz);
4541                 sh->index += sz;
4542         }
4543 }
4544
4545 struct StreamDesc {
4546         const char *name;
4547         MonoDynamicStream *stream;
4548 };
4549
4550 /*
4551  * build_compressed_metadata() fills in the blob of data that represents the 
4552  * raw metadata as it will be saved in the PE file. The five streams are output 
4553  * and the metadata tables are comnpressed from the guint32 array representation, 
4554  * to the compressed on-disk format.
4555  */
4556 static gboolean
4557 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4558 {
4559         MonoDynamicTable *table;
4560         int i;
4561         guint64 valid_mask = 0;
4562         guint64 sorted_mask;
4563         guint32 heapt_size = 0;
4564         guint32 meta_size = 256; /* allow for header and other stuff */
4565         guint32 table_offset;
4566         guint32 ntables = 0;
4567         guint64 *int64val;
4568         guint32 *int32val;
4569         guint16 *int16val;
4570         MonoImage *meta;
4571         unsigned char *p;
4572         struct StreamDesc stream_desc [5];
4573
4574         mono_error_init (error);
4575
4576         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4577         for (i = 0; i < assembly->gen_params->len; i++) {
4578                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4579                 if (!write_generic_param_entry (assembly, entry, error))
4580                         return FALSE;
4581         }
4582
4583         stream_desc [0].name  = "#~";
4584         stream_desc [0].stream = &assembly->tstream;
4585         stream_desc [1].name  = "#Strings";
4586         stream_desc [1].stream = &assembly->sheap;
4587         stream_desc [2].name  = "#US";
4588         stream_desc [2].stream = &assembly->us;
4589         stream_desc [3].name  = "#Blob";
4590         stream_desc [3].stream = &assembly->blob;
4591         stream_desc [4].name  = "#GUID";
4592         stream_desc [4].stream = &assembly->guid;
4593         
4594         /* tables that are sorted */
4595         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4596                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4597                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4598                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4599                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4600                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4601                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4602         
4603         /* Compute table sizes */
4604         /* the MonoImage has already been created in mono_image_basic_init() */
4605         meta = &assembly->image;
4606
4607         /* sizes should be multiple of 4 */
4608         pad_heap (&assembly->blob);
4609         pad_heap (&assembly->guid);
4610         pad_heap (&assembly->sheap);
4611         pad_heap (&assembly->us);
4612
4613         /* Setup the info used by compute_sizes () */
4614         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4615         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4616         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4617
4618         meta_size += assembly->blob.index;
4619         meta_size += assembly->guid.index;
4620         meta_size += assembly->sheap.index;
4621         meta_size += assembly->us.index;
4622
4623         for (i=0; i < MONO_TABLE_NUM; ++i)
4624                 meta->tables [i].rows = assembly->tables [i].rows;
4625         
4626         for (i = 0; i < MONO_TABLE_NUM; i++){
4627                 if (meta->tables [i].rows == 0)
4628                         continue;
4629                 valid_mask |= (guint64)1 << i;
4630                 ntables ++;
4631                 meta->tables [i].row_size = mono_metadata_compute_size (
4632                         meta, i, &meta->tables [i].size_bitfield);
4633                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4634         }
4635         heapt_size += 24; /* #~ header size */
4636         heapt_size += ntables * 4;
4637         /* make multiple of 4 */
4638         heapt_size += 3;
4639         heapt_size &= ~3;
4640         meta_size += heapt_size;
4641         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4642         p = (unsigned char*)meta->raw_metadata;
4643         /* the metadata signature */
4644         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4645         /* version numbers and 4 bytes reserved */
4646         int16val = (guint16*)p;
4647         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4648         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4649         p += 8;
4650         /* version string */
4651         int32val = (guint32*)p;
4652         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4653         p += 4;
4654         memcpy (p, meta->version, strlen (meta->version));
4655         p += GUINT32_FROM_LE (*int32val);
4656         align_pointer (meta->raw_metadata, p);
4657         int16val = (guint16*)p;
4658         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4659         *int16val = GUINT16_TO_LE (5); /* number of streams */
4660         p += 4;
4661
4662         /*
4663          * write the stream info.
4664          */
4665         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4666         table_offset += 3; table_offset &= ~3;
4667
4668         assembly->tstream.index = heapt_size;
4669         for (i = 0; i < 5; ++i) {
4670                 int32val = (guint32*)p;
4671                 stream_desc [i].stream->offset = table_offset;
4672                 *int32val++ = GUINT32_TO_LE (table_offset);
4673                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4674                 table_offset += GUINT32_FROM_LE (*int32val);
4675                 table_offset += 3; table_offset &= ~3;
4676                 p += 8;
4677                 strcpy ((char*)p, stream_desc [i].name);
4678                 p += strlen (stream_desc [i].name) + 1;
4679                 align_pointer (meta->raw_metadata, p);
4680         }
4681         /* 
4682          * now copy the data, the table stream header and contents goes first.
4683          */
4684         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4685         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4686         int32val = (guint32*)p;
4687         *int32val = GUINT32_TO_LE (0); /* reserved */
4688         p += 4;
4689
4690         *p++ = 2; /* version */
4691         *p++ = 0;
4692
4693         if (meta->idx_string_wide)
4694                 *p |= 0x01;
4695         if (meta->idx_guid_wide)
4696                 *p |= 0x02;
4697         if (meta->idx_blob_wide)
4698                 *p |= 0x04;
4699         ++p;
4700         *p++ = 1; /* reserved */
4701         int64val = (guint64*)p;
4702         *int64val++ = GUINT64_TO_LE (valid_mask);
4703         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4704         p += 16;
4705         int32val = (guint32*)p;
4706         for (i = 0; i < MONO_TABLE_NUM; i++){
4707                 if (meta->tables [i].rows == 0)
4708                         continue;
4709                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4710         }
4711         p = (unsigned char*)int32val;
4712
4713         /* sort the tables that still need sorting */
4714         table = &assembly->tables [MONO_TABLE_CONSTANT];
4715         if (table->rows)
4716                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4717         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4718         if (table->rows)
4719                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4720         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4721         if (table->rows)
4722                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4723         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4724         if (table->rows)
4725                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4726         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4727         if (table->rows)
4728                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4729         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4730         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4731         if (table->rows)
4732                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4733         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4734         if (table->rows)
4735                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4736
4737         /* compress the tables */
4738         for (i = 0; i < MONO_TABLE_NUM; i++){
4739                 int row, col;
4740                 guint32 *values;
4741                 guint32 bitfield = meta->tables [i].size_bitfield;
4742                 if (!meta->tables [i].rows)
4743                         continue;
4744                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4745                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4746                 meta->tables [i].base = (char*)p;
4747                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4748                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4749                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4750                                 switch (mono_metadata_table_size (bitfield, col)) {
4751                                 case 1:
4752                                         *p++ = values [col];
4753                                         break;
4754                                 case 2:
4755                                         *p++ = values [col] & 0xff;
4756                                         *p++ = (values [col] >> 8) & 0xff;
4757                                         break;
4758                                 case 4:
4759                                         *p++ = values [col] & 0xff;
4760                                         *p++ = (values [col] >> 8) & 0xff;
4761                                         *p++ = (values [col] >> 16) & 0xff;
4762                                         *p++ = (values [col] >> 24) & 0xff;
4763                                         break;
4764                                 default:
4765                                         g_assert_not_reached ();
4766                                 }
4767                         }
4768                 }
4769                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4770         }
4771         
4772         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4773         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4774         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4775         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4776         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4777
4778         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4779
4780         return TRUE;
4781 }
4782
4783 /*
4784  * Some tables in metadata need to be sorted according to some criteria, but
4785  * when methods and fields are first created with reflection, they may be assigned a token
4786  * that doesn't correspond to the final token they will get assigned after the sorting.
4787  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4788  * with the reflection objects that represent them. Once all the tables are set up, the 
4789  * reflection objects will contains the correct table index. fixup_method() will fixup the
4790  * tokens for the method with ILGenerator @ilgen.
4791  */
4792 static void
4793 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4794 {
4795         guint32 code_idx = GPOINTER_TO_UINT (value);
4796         MonoReflectionILTokenInfo *iltoken;
4797         MonoReflectionFieldBuilder *field;
4798         MonoReflectionCtorBuilder *ctor;
4799         MonoReflectionMethodBuilder *method;
4800         MonoReflectionTypeBuilder *tb;
4801         MonoReflectionArrayMethod *am;
4802         guint32 i, idx = 0;
4803         unsigned char *target;
4804
4805         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4806                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4807                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4808                 switch (target [3]) {
4809                 case MONO_TABLE_FIELD:
4810                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4811                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4812                                 idx = field->table_idx;
4813                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4814                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4815                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4816                         } else {
4817                                 g_assert_not_reached ();
4818                         }
4819                         break;
4820                 case MONO_TABLE_METHOD:
4821                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4822                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4823                                 idx = method->table_idx;
4824                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4825                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4826                                 idx = ctor->table_idx;
4827                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4828                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4829                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4830                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4831                         } else {
4832                                 g_assert_not_reached ();
4833                         }
4834                         break;
4835                 case MONO_TABLE_TYPEDEF:
4836                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4837                                 g_assert_not_reached ();
4838                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4839                         idx = tb->table_idx;
4840                         break;
4841                 case MONO_TABLE_MEMBERREF:
4842                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4843                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4844                                 idx = am->table_idx;
4845                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4846                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4847                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4848                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4849                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4850                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4851                                 continue;
4852                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4853                                 continue;
4854                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4855                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4856                                 g_assert (is_field_on_inst (f));
4857                                 continue;
4858                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4859                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4860                                 continue;
4861                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4862                                 continue;
4863                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4864                                 continue;
4865                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4866                                 continue;
4867                         } else {
4868                                 g_assert_not_reached ();
4869                         }
4870                         break;
4871                 case MONO_TABLE_METHODSPEC:
4872                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4873                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4874                                 g_assert (mono_method_signature (m)->generic_param_count);
4875                                 continue;
4876                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4877                                 continue;
4878                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4879                                 continue;
4880                         } else {
4881                                 g_assert_not_reached ();
4882                         }
4883                         break;
4884                 default:
4885                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4886                 }
4887                 target [0] = idx & 0xff;
4888                 target [1] = (idx >> 8) & 0xff;
4889                 target [2] = (idx >> 16) & 0xff;
4890         }
4891 }
4892
4893 /*
4894  * fixup_cattrs:
4895  *
4896  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4897  * value is not known when the table is emitted.
4898  */
4899 static void
4900 fixup_cattrs (MonoDynamicImage *assembly)
4901 {
4902         MonoDynamicTable *table;
4903         guint32 *values;
4904         guint32 type, i, idx, token;
4905         MonoObject *ctor;
4906
4907         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4908
4909         for (i = 0; i < table->rows; ++i) {
4910                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4911
4912                 type = values [MONO_CUSTOM_ATTR_TYPE];
4913                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4914                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4915                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4916                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4917                         g_assert (ctor);
4918
4919                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4920                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4921                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4922                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4923                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4924                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4925                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4926                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4927                         }
4928                 }
4929         }
4930 }
4931
4932 static void
4933 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4934 {
4935         MonoDynamicTable *table;
4936         guint32 *values;
4937
4938         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4939         table->rows++;
4940         alloc_table (table, table->rows);
4941         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4942         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4943         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4944         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4945         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4946         table->next_idx++;
4947 }
4948
4949 static void
4950 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4951 {
4952         MonoDynamicTable *table;
4953         guint32 *values;
4954         char blob_size [6];
4955         guchar hash [20];
4956         char *b = blob_size;
4957         char *name, *sname;
4958         guint32 idx, offset;
4959
4960         if (rsrc->filename) {
4961                 name = mono_string_to_utf8 (rsrc->filename);
4962                 sname = g_path_get_basename (name);
4963         
4964                 table = &assembly->tables [MONO_TABLE_FILE];
4965                 table->rows++;
4966                 alloc_table (table, table->rows);
4967                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4968                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4969                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4970                 g_free (sname);
4971
4972                 mono_sha1_get_digest_from_file (name, hash);
4973                 mono_metadata_encode_value (20, b, &b);
4974                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4975                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4976                 g_free (name);
4977                 idx = table->next_idx++;
4978                 rsrc->offset = 0;
4979                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4980         } else {
4981                 char sizebuf [4];
4982                 char *data;
4983                 guint len;
4984                 if (rsrc->data) {
4985                         data = mono_array_addr (rsrc->data, char, 0);
4986                         len = mono_array_length (rsrc->data);
4987                 } else {
4988                         data = NULL;
4989                         len = 0;
4990                 }
4991                 offset = len;
4992                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4993                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4994                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4995                 mono_image_add_stream_data (&assembly->resources, data, len);
4996
4997                 if (!mb->is_main)
4998                         /* 
4999                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5000                          * the main module, but that needs to reference the FILE table
5001                          * which isn't emitted yet.
5002                          */
5003                         return;
5004                 else
5005                         idx = 0;
5006         }
5007
5008         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5009 }
5010
5011 static void
5012 set_version_from_string (MonoString *version, guint32 *values)
5013 {
5014         gchar *ver, *p, *str;
5015         guint32 i;
5016         
5017         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5018         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5019         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5020         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5021         if (!version)
5022                 return;
5023         ver = str = mono_string_to_utf8 (version);
5024         for (i = 0; i < 4; ++i) {
5025                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5026                 switch (*p) {
5027                 case '.':
5028                         p++;
5029                         break;
5030                 case '*':
5031                         /* handle Revision and Build */
5032                         p++;
5033                         break;
5034                 }
5035                 ver = p;
5036         }
5037         g_free (str);
5038 }
5039
5040 static guint32
5041 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5042         gsize len;
5043         guint32 token = 0;
5044         char blob_size [6];
5045         char *b = blob_size;
5046
5047         if (!pkey)
5048                 return token;
5049
5050         len = mono_array_length (pkey);
5051         mono_metadata_encode_value (len, b, &b);
5052         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5053         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5054
5055         assembly->public_key = (guint8 *)g_malloc (len);
5056         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5057         assembly->public_key_len = len;
5058
5059         /* Special case: check for ECMA key (16 bytes) */
5060         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5061                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5062                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5063         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5064                 /* minimum key size (in 2.0) is 384 bits */
5065                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5066         } else {
5067                 /* FIXME - verifier */
5068                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5069                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5070         }
5071         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5072
5073         return token;
5074 }
5075
5076 static void
5077 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5078 {
5079         MonoDynamicTable *table;
5080         MonoDynamicImage *assembly;
5081         MonoReflectionAssemblyBuilder *assemblyb;
5082         MonoDomain *domain;
5083         guint32 *values;
5084         int i;
5085         guint32 module_index;
5086
5087         mono_error_init (error);
5088
5089         assemblyb = moduleb->assemblyb;
5090         assembly = moduleb->dynamic_image;
5091         domain = mono_object_domain (assemblyb);
5092
5093         /* Emit ASSEMBLY table */
5094         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5095         alloc_table (table, 1);
5096         values = table->values + MONO_ASSEMBLY_SIZE;
5097         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5098         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5099         if (assemblyb->culture) {
5100                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5101         } else {
5102                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5103         }
5104         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5105         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5106         set_version_from_string (assemblyb->version, values);
5107
5108         /* Emit FILE + EXPORTED_TYPE table */
5109         module_index = 0;
5110         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5111                 int j;
5112                 MonoReflectionModuleBuilder *file_module = 
5113                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5114                 if (file_module != moduleb) {
5115                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5116                         module_index ++;
5117                         if (file_module->types) {
5118                                 for (j = 0; j < file_module->num_types; ++j) {
5119                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5120                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5121                                         return_if_nok (error);
5122                                 }
5123                         }
5124                 }
5125         }
5126         if (assemblyb->loaded_modules) {
5127                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5128                         MonoReflectionModule *file_module = 
5129                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5130                         mono_image_fill_file_table (domain, file_module, assembly);
5131                         module_index ++;
5132                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5133                 }
5134         }
5135         if (assemblyb->type_forwarders)
5136                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5137
5138         /* Emit MANIFESTRESOURCE table */
5139         module_index = 0;
5140         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5141                 int j;
5142                 MonoReflectionModuleBuilder *file_module = 
5143                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5144                 /* The table for the main module is emitted later */
5145                 if (file_module != moduleb) {
5146                         module_index ++;
5147                         if (file_module->resources) {
5148                                 int len = mono_array_length (file_module->resources);
5149                                 for (j = 0; j < len; ++j) {
5150                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5151                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5152                                 }
5153                         }
5154                 }
5155         }               
5156 }
5157
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5159
5160 /*
5161  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5162  * for the modulebuilder @moduleb.
5163  * At the end of the process, method and field tokens are fixed up and the 
5164  * on-disk compressed metadata representation is created.
5165  * Return TRUE on success, or FALSE on failure and sets @error
5166  */
5167 gboolean
5168 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5169 {
5170         MonoDynamicTable *table;
5171         MonoDynamicImage *assembly;
5172         MonoReflectionAssemblyBuilder *assemblyb;
5173         MonoDomain *domain;
5174         MonoPtrArray types;
5175         guint32 *values;
5176         int i, j;
5177
5178         mono_error_init (error);
5179
5180         assemblyb = moduleb->assemblyb;
5181         assembly = moduleb->dynamic_image;
5182         domain = mono_object_domain (assemblyb);
5183
5184         if (assembly->text_rva)
5185                 return TRUE;
5186
5187         assembly->text_rva = START_TEXT_RVA;
5188
5189         if (moduleb->is_main) {
5190                 mono_image_emit_manifest (moduleb, error);
5191                 return_val_if_nok (error, FALSE);
5192         }
5193
5194         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5195         table->rows = 1; /* .<Module> */
5196         table->next_idx++;
5197         alloc_table (table, table->rows);
5198         /*
5199          * Set the first entry.
5200          */
5201         values = table->values + table->columns;
5202         values [MONO_TYPEDEF_FLAGS] = 0;
5203         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5204         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5205         values [MONO_TYPEDEF_EXTENDS] = 0;
5206         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5207         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5208
5209         /* 
5210          * handle global methods 
5211          * FIXME: test what to do when global methods are defined in multiple modules.
5212          */
5213         if (moduleb->global_methods) {
5214                 table = &assembly->tables [MONO_TABLE_METHOD];
5215                 table->rows += mono_array_length (moduleb->global_methods);
5216                 alloc_table (table, table->rows);
5217                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5218                         if (!mono_image_get_method_info (
5219                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5220                                 goto leave;
5221                 }
5222         }
5223         if (moduleb->global_fields) {
5224                 table = &assembly->tables [MONO_TABLE_FIELD];
5225                 table->rows += mono_array_length (moduleb->global_fields);
5226                 alloc_table (table, table->rows);
5227                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5228                         mono_image_get_field_info (
5229                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5230                                 error);
5231                         if (!is_ok (error))
5232                                 goto leave;
5233                 }
5234         }
5235
5236         table = &assembly->tables [MONO_TABLE_MODULE];
5237         alloc_table (table, 1);
5238         mono_image_fill_module_table (domain, moduleb, assembly);
5239
5240         /* Collect all types into a list sorted by their table_idx */
5241         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5242
5243         if (moduleb->types)
5244                 for (i = 0; i < moduleb->num_types; ++i) {
5245                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5246                         collect_types (&types, type);
5247                 }
5248
5249         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5250         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5251         table->rows += mono_ptr_array_size (types);
5252         alloc_table (table, table->rows);
5253
5254         /*
5255          * Emit type names + namespaces at one place inside the string heap,
5256          * so load_class_names () needs to touch fewer pages.
5257          */
5258         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5259                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5260                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5261         }
5262         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5263                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5264                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5265         }
5266
5267         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5268                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5269                 if (!mono_image_get_type_info (domain, type, assembly, error))
5270                         goto leave_types;
5271         }
5272
5273         /* 
5274          * table->rows is already set above and in mono_image_fill_module_table.
5275          */
5276         /* add all the custom attributes at the end, once all the indexes are stable */
5277         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5278                 goto leave_types;
5279
5280         /* CAS assembly permissions */
5281         if (assemblyb->permissions_minimum)
5282                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5283         if (assemblyb->permissions_optional)
5284                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5285         if (assemblyb->permissions_refused)
5286                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5287
5288         if (!module_add_cattrs (assembly, moduleb, error))
5289                 goto leave_types;
5290
5291         /* fixup tokens */
5292         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5293
5294         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5295          * the final tokens and don't need another fixup pass. */
5296
5297         if (moduleb->global_methods) {
5298                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5299                         MonoReflectionMethodBuilder *mb = mono_array_get (
5300                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5301                         if (!mono_image_add_methodimpl (assembly, mb, error))
5302                                 goto leave_types;
5303                 }
5304         }
5305
5306         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308                 if (type->methods) {
5309                         for (j = 0; j < type->num_methods; ++j) {
5310                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5311                                         type->methods, MonoReflectionMethodBuilder*, j);
5312
5313                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5314                                         goto leave_types;
5315                         }
5316                 }
5317         }
5318
5319         fixup_cattrs (assembly);
5320
5321 leave_types:
5322         mono_ptr_array_destroy (types);
5323 leave:
5324
5325         return mono_error_ok (error);
5326 }
5327
5328 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5329
5330 gboolean
5331 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5332 {
5333         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5334 }
5335
5336 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5337
5338
5339 typedef struct {
5340         guint32 import_lookup_table;
5341         guint32 timestamp;
5342         guint32 forwarder;
5343         guint32 name_rva;
5344         guint32 import_address_table_rva;
5345 } MonoIDT;
5346
5347 typedef struct {
5348         guint32 name_rva;
5349         guint32 flags;
5350 } MonoILT;
5351
5352 #ifndef DISABLE_REFLECTION_EMIT
5353
5354 /*
5355  * mono_image_insert_string:
5356  * @module: module builder object
5357  * @str: a string
5358  *
5359  * Insert @str into the user string stream of @module.
5360  */
5361 guint32
5362 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5363 {
5364         MonoDynamicImage *assembly;
5365         guint32 idx;
5366         char buf [16];
5367         char *b = buf;
5368         
5369         if (!module->dynamic_image)
5370                 mono_image_module_basic_init (module);
5371
5372         assembly = module->dynamic_image;
5373         
5374         if (assembly->save) {
5375                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5376                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5378         {
5379                 char *swapped = g_malloc (2 * mono_string_length (str));
5380                 const char *p = (const char*)mono_string_chars (str);
5381
5382                 swap_with_size (swapped, p, 2, mono_string_length (str));
5383                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5384                 g_free (swapped);
5385         }
5386 #else
5387                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5388 #endif
5389                 mono_image_add_stream_data (&assembly->us, "", 1);
5390         } else {
5391                 idx = assembly->us.index ++;
5392         }
5393
5394         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5395
5396         return MONO_TOKEN_STRING | idx;
5397 }
5398
5399 guint32
5400 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5401 {
5402         MonoClass *klass;
5403         guint32 token = 0;
5404         MonoMethodSignature *sig;
5405
5406         mono_error_init (error);
5407
5408         klass = obj->vtable->klass;
5409         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5410                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5411                 MonoMethodSignature *old;
5412                 guint32 sig_token, parent;
5413                 int nargs, i;
5414
5415                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5416
5417                 nargs = mono_array_length (opt_param_types);
5418                 old = mono_method_signature (method);
5419                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5420
5421                 sig->hasthis = old->hasthis;
5422                 sig->explicit_this = old->explicit_this;
5423                 sig->call_convention = old->call_convention;
5424                 sig->generic_param_count = old->generic_param_count;
5425                 sig->param_count = old->param_count + nargs;
5426                 sig->sentinelpos = old->param_count;
5427                 sig->ret = old->ret;
5428
5429                 for (i = 0; i < old->param_count; i++)
5430                         sig->params [i] = old->params [i];
5431
5432                 for (i = 0; i < nargs; i++) {
5433                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5434                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5435                         if (!is_ok (error)) goto fail;
5436                 }
5437
5438                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5439                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5440                 parent >>= MONO_TYPEDEFORREF_BITS;
5441
5442                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5443                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5444
5445                 sig_token = method_encode_signature (assembly, sig);
5446                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5447         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5448                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5449                 ReflectionMethodBuilder rmb;
5450                 guint32 parent, sig_token;
5451                 int nopt_args, nparams, ngparams, i;
5452
5453                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5454                         goto fail;
5455                 
5456                 rmb.opt_types = opt_param_types;
5457                 nopt_args = mono_array_length (opt_param_types);
5458
5459                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5460                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5461                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5462
5463                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5464                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5465                 sig->call_convention = rmb.call_conv;
5466                 sig->generic_param_count = ngparams;
5467                 sig->param_count = nparams + nopt_args;
5468                 sig->sentinelpos = nparams;
5469                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5470                 if (!is_ok (error)) goto fail;
5471
5472                 for (i = 0; i < nparams; i++) {
5473                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5474                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5475                         if (!is_ok (error)) goto fail;
5476                 }
5477
5478                 for (i = 0; i < nopt_args; i++) {
5479                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5480                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5481                         if (!is_ok (error)) goto fail;
5482                 }
5483
5484                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5485                 if (!is_ok (error))
5486                         goto fail;
5487
5488                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5489                 if (!mono_error_ok (error))
5490                         goto fail;
5491                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5492
5493                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5494                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5495
5496                 char *name = mono_string_to_utf8 (rmb.name);
5497                 token = mono_image_get_varargs_method_token (
5498                         assembly, parent, name, sig_token);
5499                 g_free (name);
5500         } else {
5501                 g_error ("requested method token for %s\n", klass->name);
5502         }
5503
5504         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5505         register_dyn_token (assembly, token, obj);
5506         return token;
5507 fail:
5508         g_assert (!mono_error_ok (error));
5509         return 0;
5510 }
5511
5512 /*
5513  * mono_image_create_token:
5514  * @assembly: a dynamic assembly
5515  * @obj:
5516  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5517  *
5518  * Get a token to insert in the IL code stream for the given MemberInfo.
5519  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5520  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5521  * entry.
5522  */
5523 guint32
5524 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5525                          gboolean create_open_instance, gboolean register_token,
5526                          MonoError *error)
5527 {
5528         MonoClass *klass;
5529         guint32 token = 0;
5530
5531         mono_error_init (error);
5532
5533         klass = obj->vtable->klass;
5534
5535         /* Check for user defined reflection objects */
5536         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5537         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5538                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5539                 return 0;
5540         }
5541
5542         if (strcmp (klass->name, "MethodBuilder") == 0) {
5543                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5544                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5545
5546                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5547                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5548                 else {
5549                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5550                         if (!mono_error_ok (error))
5551                                 return 0;
5552                 }
5553                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5554         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5555                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5556                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5557
5558                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5559                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5560                 else {
5561                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5562                         if (!mono_error_ok (error))
5563                                 return 0;
5564                 }
5565                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5566         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5567                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5568                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5569                 if (tb->generic_params) {
5570                         token = mono_image_get_generic_field_token (assembly, fb, error);
5571                         return_val_if_nok (error, 0);
5572                 } else {
5573                         if (tb->module->dynamic_image == assembly) {
5574                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5575                         } else {
5576                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5577                         }
5578                 }
5579         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5580                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5581                 if (create_open_instance && tb->generic_params) {
5582                         MonoType *type;
5583                         init_type_builder_generics (obj);
5584                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5585                         return_val_if_nok (error, 0);
5586                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5587                         token = mono_metadata_token_from_dor (token);
5588                 } else if (tb->module->dynamic_image == assembly) {
5589                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5590                 } else {
5591                         MonoType *type;
5592                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5593                         return_val_if_nok (error, 0);
5594                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5595                 }
5596         } else if (strcmp (klass->name, "MonoType") == 0) {
5597                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5598                 return_val_if_nok (error, 0);
5599                 MonoClass *mc = mono_class_from_mono_type (type);
5600                 token = mono_metadata_token_from_dor (
5601                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5602         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5603                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5604                 return_val_if_nok (error, 0);
5605                 token = mono_metadata_token_from_dor (
5606                         mono_image_typedef_or_ref (assembly, type));
5607         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5608                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5609                 return_val_if_nok (error, 0);
5610                 token = mono_metadata_token_from_dor (
5611                         mono_image_typedef_or_ref (assembly, type));
5612         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5613                    strcmp (klass->name, "MonoMethod") == 0 ||
5614                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5615                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5616                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5617                 if (m->method->is_inflated) {
5618                         if (create_open_instance)
5619                                 token = mono_image_get_methodspec_token (assembly, m->method);
5620                         else
5621                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5622                 } else if ((m->method->klass->image == &assembly->image) &&
5623                          !m->method->klass->generic_class) {
5624                         static guint32 method_table_idx = 0xffffff;
5625                         if (m->method->klass->wastypebuilder) {
5626                                 /* we use the same token as the one that was assigned
5627                                  * to the Methodbuilder.
5628                                  * FIXME: do the equivalent for Fields.
5629                                  */
5630                                 token = m->method->token;
5631                         } else {
5632                                 /*
5633                                  * Each token should have a unique index, but the indexes are
5634                                  * assigned by managed code, so we don't know about them. An
5635                                  * easy solution is to count backwards...
5636                                  */
5637                                 method_table_idx --;
5638                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5639                         }
5640                 } else {
5641                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5642                 }
5643                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5644         } else if (strcmp (klass->name, "MonoField") == 0) {
5645                 MonoReflectionField *f = (MonoReflectionField *)obj;
5646                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5647                         static guint32 field_table_idx = 0xffffff;
5648                         field_table_idx --;
5649                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5650                 } else {
5651                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5652                 }
5653                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5654         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5655                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5656                 token = mono_image_get_array_token (assembly, m, error);
5657                 return_val_if_nok (error, 0);
5658         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5659                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5660                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5661                 return_val_if_nok (error, 0);
5662         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5663                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5664                 return_val_if_nok (error, 0);
5665                 token = mono_metadata_token_from_dor (
5666                         mono_image_typedef_or_ref (assembly, type));
5667         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5668                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5669                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5670                 return_val_if_nok (error, 0);
5671         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5672                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5673                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5674                 if (!mono_error_ok (error))
5675                         return 0;
5676         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5677                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5678                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5679                 if (!mono_error_ok (error))
5680                         return 0;
5681         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5682                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5683                 return_val_if_nok (error, 0);
5684                 token = mono_metadata_token_from_dor (
5685                                 mono_image_typedef_or_ref (assembly, type));
5686         } else {
5687                 g_error ("requested token for %s\n", klass->name);
5688         }
5689
5690         if (register_token)
5691                 mono_image_register_token (assembly, token, obj);
5692
5693         return token;
5694 }
5695
5696 /*
5697  * mono_image_register_token:
5698  *
5699  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5700  * the Module.ResolveXXXToken () methods to work.
5701  */
5702 void
5703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5704 {
5705         MonoObject *prev;
5706
5707         dynamic_image_lock (assembly);
5708         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5709         if (prev) {
5710                 /* There could be multiple MethodInfo objects with the same token */
5711                 //g_assert (prev == obj);
5712         } else {
5713                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5714         }
5715         dynamic_image_unlock (assembly);
5716 }
5717
5718 static MonoDynamicImage*
5719 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5720 {
5721         static const guchar entrycode [16] = {0xff, 0x25, 0};
5722         MonoDynamicImage *image;
5723         int i;
5724
5725         const char *version;
5726
5727         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5728                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5729         else
5730                 version = mono_get_runtime_info ()->runtime_version;
5731
5732 #if HAVE_BOEHM_GC
5733         /* The MonoGHashTable's need GC tracking */
5734         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5735 #else
5736         image = g_new0 (MonoDynamicImage, 1);
5737 #endif
5738
5739         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5740         
5741         /*g_print ("created image %p\n", image);*/
5742         /* keep in sync with image.c */
5743         image->image.name = assembly_name;
5744         image->image.assembly_name = image->image.name; /* they may be different */
5745         image->image.module_name = module_name;
5746         image->image.version = g_strdup (version);
5747         image->image.md_version_major = 1;
5748         image->image.md_version_minor = 1;
5749         image->image.dynamic = TRUE;
5750
5751         image->image.references = g_new0 (MonoAssembly*, 1);
5752         image->image.references [0] = NULL;
5753
5754         mono_image_init (&image->image);
5755
5756         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");
5757         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5758         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5759         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5760         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5761         image->handleref = g_hash_table_new (NULL, NULL);
5762         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");
5763         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5764         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");
5765         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");
5766         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5767         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5769         image->gen_params = g_ptr_array_new ();
5770         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5771
5772         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5773         string_heap_init (&image->sheap);
5774         mono_image_add_stream_data (&image->us, "", 1);
5775         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5776         /* import tables... */
5777         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5778         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5779         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5780         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5781         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5782         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5783         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5784         stream_data_align (&image->code);
5785
5786         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5787
5788         for (i=0; i < MONO_TABLE_NUM; ++i) {
5789                 image->tables [i].next_idx = 1;
5790                 image->tables [i].columns = table_sizes [i];
5791         }
5792
5793         image->image.assembly = (MonoAssembly*)assembly;
5794         image->run = assembly->run;
5795         image->save = assembly->save;
5796         image->pe_kind = 0x1; /* ILOnly */
5797         image->machine = 0x14c; /* I386 */
5798         
5799         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5800
5801         dynamic_images_lock ();
5802
5803         if (!dynamic_images)
5804                 dynamic_images = g_ptr_array_new ();
5805
5806         g_ptr_array_add (dynamic_images, image);
5807
5808         dynamic_images_unlock ();
5809
5810         return image;
5811 }
5812 #endif
5813
5814 static void
5815 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5816 {
5817         g_free (key);
5818 }
5819
5820 static void
5821 release_hashtable (MonoGHashTable **hash)
5822 {
5823         if (*hash) {
5824                 mono_g_hash_table_destroy (*hash);
5825                 *hash = NULL;
5826         }
5827 }
5828
5829 void
5830 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5831 {
5832         release_hashtable (&image->token_fixups);
5833         release_hashtable (&image->handleref_managed);
5834         release_hashtable (&image->tokens);
5835         release_hashtable (&image->remapped_tokens);
5836         release_hashtable (&image->generic_def_objects);
5837         release_hashtable (&image->methodspec);
5838 }
5839
5840 // Free dynamic image pass one: Free resources but not image itself
5841 void
5842 mono_dynamic_image_free (MonoDynamicImage *image)
5843 {
5844         MonoDynamicImage *di = image;
5845         GList *list;
5846         int i;
5847
5848         if (di->methodspec)
5849                 mono_g_hash_table_destroy (di->methodspec);
5850         if (di->typespec)
5851                 g_hash_table_destroy (di->typespec);
5852         if (di->typeref)
5853                 g_hash_table_destroy (di->typeref);
5854         if (di->handleref)
5855                 g_hash_table_destroy (di->handleref);
5856         if (di->handleref_managed)
5857                 mono_g_hash_table_destroy (di->handleref_managed);
5858         if (di->tokens)
5859                 mono_g_hash_table_destroy (di->tokens);
5860         if (di->remapped_tokens)
5861                 mono_g_hash_table_destroy (di->remapped_tokens);
5862         if (di->generic_def_objects)
5863                 mono_g_hash_table_destroy (di->generic_def_objects);
5864         if (di->blob_cache) {
5865                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5866                 g_hash_table_destroy (di->blob_cache);
5867         }
5868         if (di->standalonesig_cache)
5869                 g_hash_table_destroy (di->standalonesig_cache);
5870         for (list = di->array_methods; list; list = list->next) {
5871                 ArrayMethod *am = (ArrayMethod *)list->data;
5872                 g_free (am->sig);
5873                 g_free (am->name);
5874                 g_free (am);
5875         }
5876         g_list_free (di->array_methods);
5877         if (di->gen_params) {
5878                 for (i = 0; i < di->gen_params->len; i++) {
5879                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5880                         mono_gc_deregister_root ((char*) &entry->gparam);
5881                         g_free (entry);
5882                 }
5883                 g_ptr_array_free (di->gen_params, TRUE);
5884         }
5885         if (di->token_fixups)
5886                 mono_g_hash_table_destroy (di->token_fixups);
5887         if (di->method_to_table_idx)
5888                 g_hash_table_destroy (di->method_to_table_idx);
5889         if (di->field_to_table_idx)
5890                 g_hash_table_destroy (di->field_to_table_idx);
5891         if (di->method_aux_hash)
5892                 g_hash_table_destroy (di->method_aux_hash);
5893         if (di->vararg_aux_hash)
5894                 g_hash_table_destroy (di->vararg_aux_hash);
5895         g_free (di->strong_name);
5896         g_free (di->win32_res);
5897         if (di->public_key)
5898                 g_free (di->public_key);
5899
5900         /*g_print ("string heap destroy for image %p\n", di);*/
5901         mono_dynamic_stream_reset (&di->sheap);
5902         mono_dynamic_stream_reset (&di->code);
5903         mono_dynamic_stream_reset (&di->resources);
5904         mono_dynamic_stream_reset (&di->us);
5905         mono_dynamic_stream_reset (&di->blob);
5906         mono_dynamic_stream_reset (&di->tstream);
5907         mono_dynamic_stream_reset (&di->guid);
5908         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5909                 g_free (di->tables [i].values);
5910         }
5911
5912         dynamic_images_lock ();
5913
5914         if (dynamic_images)
5915                 g_ptr_array_remove (dynamic_images, di);
5916
5917         dynamic_images_unlock ();
5918 }
5919
5920 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5921 void
5922 mono_dynamic_image_free_image (MonoDynamicImage *image)
5923 {
5924         /* See create_dynamic_mono_image () */
5925 #if HAVE_BOEHM_GC
5926         /* Allocated using GC_MALLOC */
5927 #else
5928         g_free (image);
5929 #endif
5930 }
5931
5932 #ifndef DISABLE_REFLECTION_EMIT
5933
5934 /*
5935  * mono_image_basic_init:
5936  * @assembly: an assembly builder object
5937  *
5938  * Create the MonoImage that represents the assembly builder and setup some
5939  * of the helper hash table and the basic metadata streams.
5940  */
5941 void
5942 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5943 {
5944         MonoDynamicAssembly *assembly;
5945         MonoDynamicImage *image;
5946         MonoDomain *domain = mono_object_domain (assemblyb);
5947         
5948         if (assemblyb->dynamic_assembly)
5949                 return;
5950
5951 #if HAVE_BOEHM_GC
5952         /* assembly->assembly.image might be GC allocated */
5953         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5954 #else
5955         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5956 #endif
5957
5958         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5959         
5960         assembly->assembly.ref_count = 1;
5961         assembly->assembly.dynamic = TRUE;
5962         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5963         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5964         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5965         if (assemblyb->culture)
5966                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5967         else
5968                 assembly->assembly.aname.culture = g_strdup ("");
5969
5970         if (assemblyb->version) {
5971                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5972                         char **version = g_strsplit (vstr, ".", 4);
5973                         char **parts = version;
5974                         assembly->assembly.aname.major = atoi (*parts++);
5975                         assembly->assembly.aname.minor = atoi (*parts++);
5976                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5977                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5978
5979                         g_strfreev (version);
5980                         g_free (vstr);
5981         } else {
5982                         assembly->assembly.aname.major = 0;
5983                         assembly->assembly.aname.minor = 0;
5984                         assembly->assembly.aname.build = 0;
5985                         assembly->assembly.aname.revision = 0;
5986         }
5987
5988         assembly->run = assemblyb->access != 2;
5989         assembly->save = assemblyb->access != 1;
5990         assembly->domain = domain;
5991
5992         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5993         image->initial_image = TRUE;
5994         assembly->assembly.aname.name = image->image.name;
5995         assembly->assembly.image = &image->image;
5996         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5997                 /* -1 to correct for the trailing NULL byte */
5998                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5999                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6000                 }
6001                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6002         }
6003
6004         mono_domain_assemblies_lock (domain);
6005         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6006         mono_domain_assemblies_unlock (domain);
6007
6008         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6009         
6010         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6011         
6012         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6013 }
6014
6015 #endif /* !DISABLE_REFLECTION_EMIT */
6016
6017 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6018
6019 static int
6020 calc_section_size (MonoDynamicImage *assembly)
6021 {
6022         int nsections = 0;
6023
6024         /* alignment constraints */
6025         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6026         g_assert ((assembly->code.index % 4) == 0);
6027         assembly->meta_size += 3;
6028         assembly->meta_size &= ~3;
6029         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6030         g_assert ((assembly->resources.index % 4) == 0);
6031
6032         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6033         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6034         nsections++;
6035
6036         if (assembly->win32_res) {
6037                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6038
6039                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6040                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6041                 nsections++;
6042         }
6043
6044         assembly->sections [MONO_SECTION_RELOC].size = 12;
6045         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6046         nsections++;
6047
6048         return nsections;
6049 }
6050
6051 typedef struct {
6052         guint32 id;
6053         guint32 offset;
6054         GSList *children;
6055         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6056 } ResTreeNode;
6057
6058 static int
6059 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6060 {
6061         ResTreeNode *t1 = (ResTreeNode*)a;
6062         ResTreeNode *t2 = (ResTreeNode*)b;
6063
6064         return t1->id - t2->id;
6065 }
6066
6067 /*
6068  * resource_tree_create:
6069  *
6070  *  Organize the resources into a resource tree.
6071  */
6072 static ResTreeNode *
6073 resource_tree_create (MonoArray *win32_resources)
6074 {
6075         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6076         GSList *l;
6077         int i;
6078
6079         tree = g_new0 (ResTreeNode, 1);
6080         
6081         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6082                 MonoReflectionWin32Resource *win32_res =
6083                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6084
6085                 /* Create node */
6086
6087                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6088                 lang_node = g_new0 (ResTreeNode, 1);
6089                 lang_node->id = win32_res->lang_id;
6090                 lang_node->win32_res = win32_res;
6091
6092                 /* Create type node if neccesary */
6093                 type_node = NULL;
6094                 for (l = tree->children; l; l = l->next)
6095                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6096                                 type_node = (ResTreeNode*)l->data;
6097                                 break;
6098                         }
6099
6100                 if (!type_node) {
6101                         type_node = g_new0 (ResTreeNode, 1);
6102                         type_node->id = win32_res->res_type;
6103
6104                         /* 
6105                          * The resource types have to be sorted otherwise
6106                          * Windows Explorer can't display the version information.
6107                          */
6108                         tree->children = g_slist_insert_sorted (tree->children, 
6109                                 type_node, resource_tree_compare_by_id);
6110                 }
6111
6112                 /* Create res node if neccesary */
6113                 res_node = NULL;
6114                 for (l = type_node->children; l; l = l->next)
6115                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6116                                 res_node = (ResTreeNode*)l->data;
6117                                 break;
6118                         }
6119
6120                 if (!res_node) {
6121                         res_node = g_new0 (ResTreeNode, 1);
6122                         res_node->id = win32_res->res_id;
6123                         type_node->children = g_slist_append (type_node->children, res_node);
6124                 }
6125
6126                 res_node->children = g_slist_append (res_node->children, lang_node);
6127         }
6128
6129         return tree;
6130 }
6131
6132 /*
6133  * resource_tree_encode:
6134  * 
6135  *   Encode the resource tree into the format used in the PE file.
6136  */
6137 static void
6138 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6139 {
6140         char *entries;
6141         MonoPEResourceDir dir;
6142         MonoPEResourceDirEntry dir_entry;
6143         MonoPEResourceDataEntry data_entry;
6144         GSList *l;
6145         guint32 res_id_entries;
6146
6147         /*
6148          * For the format of the resource directory, see the article
6149          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6150          * Matt Pietrek
6151          */
6152
6153         memset (&dir, 0, sizeof (dir));
6154         memset (&dir_entry, 0, sizeof (dir_entry));
6155         memset (&data_entry, 0, sizeof (data_entry));
6156
6157         g_assert (sizeof (dir) == 16);
6158         g_assert (sizeof (dir_entry) == 8);
6159         g_assert (sizeof (data_entry) == 16);
6160
6161         node->offset = p - begin;
6162
6163         /* IMAGE_RESOURCE_DIRECTORY */
6164         res_id_entries = g_slist_length (node->children);
6165         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6166
6167         memcpy (p, &dir, sizeof (dir));
6168         p += sizeof (dir);
6169
6170         /* Reserve space for entries */
6171         entries = p;
6172         p += sizeof (dir_entry) * res_id_entries;
6173
6174         /* Write children */
6175         for (l = node->children; l; l = l->next) {
6176                 ResTreeNode *child = (ResTreeNode*)l->data;
6177
6178                 if (child->win32_res) {
6179                         guint32 size;
6180
6181                         child->offset = p - begin;
6182
6183                         /* IMAGE_RESOURCE_DATA_ENTRY */
6184                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6185                         size = mono_array_length (child->win32_res->res_data);
6186                         data_entry.rde_size = GUINT32_TO_LE (size);
6187
6188                         memcpy (p, &data_entry, sizeof (data_entry));
6189                         p += sizeof (data_entry);
6190
6191                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6192                         p += size;
6193                 } else {
6194                         resource_tree_encode (child, begin, p, &p);
6195                 }
6196         }
6197
6198         /* IMAGE_RESOURCE_ENTRY */
6199         for (l = node->children; l; l = l->next) {
6200                 ResTreeNode *child = (ResTreeNode*)l->data;
6201
6202                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6203                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6204
6205                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6206                 entries += sizeof (dir_entry);
6207         }
6208
6209         *endbuf = p;
6210 }
6211
6212 static void
6213 resource_tree_free (ResTreeNode * node)
6214 {
6215         GSList * list;
6216         for (list = node->children; list; list = list->next)
6217                 resource_tree_free ((ResTreeNode*)list->data);
6218         g_slist_free(node->children);
6219         g_free (node);
6220 }
6221
6222 static void
6223 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6224 {
6225         char *buf;
6226         char *p;
6227         guint32 size, i;
6228         MonoReflectionWin32Resource *win32_res;
6229         ResTreeNode *tree;
6230
6231         if (!assemblyb->win32_resources)
6232                 return;
6233
6234         /*
6235          * Resources are stored in a three level tree inside the PE file.
6236          * - level one contains a node for each type of resource
6237          * - level two contains a node for each resource
6238          * - level three contains a node for each instance of a resource for a
6239          *   specific language.
6240          */
6241
6242         tree = resource_tree_create (assemblyb->win32_resources);
6243
6244         /* Estimate the size of the encoded tree */
6245         size = 0;
6246         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6247                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6248                 size += mono_array_length (win32_res->res_data);
6249         }
6250         /* Directory structure */
6251         size += mono_array_length (assemblyb->win32_resources) * 256;
6252         p = buf = (char *)g_malloc (size);
6253
6254         resource_tree_encode (tree, p, p, &p);
6255
6256         g_assert (p - buf <= size);
6257
6258         assembly->win32_res = (char *)g_malloc (p - buf);
6259         assembly->win32_res_size = p - buf;
6260         memcpy (assembly->win32_res, buf, p - buf);
6261
6262         g_free (buf);
6263         resource_tree_free (tree);
6264 }
6265
6266 static void
6267 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6268 {
6269         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6270         int i;
6271
6272         p += sizeof (MonoPEResourceDir);
6273         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6274                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6275                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6276                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6277                         fixup_resource_directory (res_section, child, rva);
6278                 } else {
6279                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6280                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6281                 }
6282
6283                 p += sizeof (MonoPEResourceDirEntry);
6284         }
6285 }
6286
6287 static void
6288 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6289 {
6290         guint32 dummy;
6291         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6292                 g_error ("WriteFile returned %d\n", GetLastError ());
6293 }
6294
6295 /*
6296  * mono_image_create_pefile:
6297  * @mb: a module builder object
6298  * 
6299  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6300  * assembly->pefile where it can be easily retrieved later in chunks.
6301  */
6302 gboolean
6303 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6304 {
6305         MonoMSDOSHeader *msdos;
6306         MonoDotNetHeader *header;
6307         MonoSectionTable *section;
6308         MonoCLIHeader *cli_header;
6309         guint32 size, image_size, virtual_base, text_offset;
6310         guint32 header_start, section_start, file_offset, virtual_offset;
6311         MonoDynamicImage *assembly;
6312         MonoReflectionAssemblyBuilder *assemblyb;
6313         MonoDynamicStream pefile_stream = {0};
6314         MonoDynamicStream *pefile = &pefile_stream;
6315         int i, nsections;
6316         guint32 *rva, value;
6317         guchar *p;
6318         static const unsigned char msheader[] = {
6319                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6320                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6321                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6323                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6324                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6325                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6326                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6327         };
6328
6329         mono_error_init (error);
6330
6331         assemblyb = mb->assemblyb;
6332
6333         mono_image_basic_init (assemblyb);
6334         assembly = mb->dynamic_image;
6335
6336         assembly->pe_kind = assemblyb->pe_kind;
6337         assembly->machine = assemblyb->machine;
6338         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6339         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6340         
6341         if (!mono_image_build_metadata (mb, error))
6342                 return FALSE;
6343         
6344
6345         if (mb->is_main && assemblyb->resources) {
6346                 int len = mono_array_length (assemblyb->resources);
6347                 for (i = 0; i < len; ++i)
6348                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6349         }
6350
6351         if (mb->resources) {
6352                 int len = mono_array_length (mb->resources);
6353                 for (i = 0; i < len; ++i)
6354                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6355         }
6356
6357         if (!build_compressed_metadata (assembly, error))
6358                 return FALSE;
6359
6360         if (mb->is_main)
6361                 assembly_add_win32_resources (assembly, assemblyb);
6362
6363         nsections = calc_section_size (assembly);
6364         
6365         /* The DOS header and stub */
6366         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6367         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6368
6369         /* the dotnet header */
6370         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6371
6372         /* the section tables */
6373         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6374
6375         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6376         virtual_offset = VIRT_ALIGN;
6377         image_size = 0;
6378
6379         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6380                 if (!assembly->sections [i].size)
6381                         continue;
6382                 /* align offsets */
6383                 file_offset += FILE_ALIGN - 1;
6384                 file_offset &= ~(FILE_ALIGN - 1);
6385                 virtual_offset += VIRT_ALIGN - 1;
6386                 virtual_offset &= ~(VIRT_ALIGN - 1);
6387
6388                 assembly->sections [i].offset = file_offset;
6389                 assembly->sections [i].rva = virtual_offset;
6390
6391                 file_offset += assembly->sections [i].size;
6392                 virtual_offset += assembly->sections [i].size;
6393                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6394         }
6395
6396         file_offset += FILE_ALIGN - 1;
6397         file_offset &= ~(FILE_ALIGN - 1);
6398
6399         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6400
6401         /* back-patch info */
6402         msdos = (MonoMSDOSHeader*)pefile->data;
6403         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6404
6405         header = (MonoDotNetHeader*)(pefile->data + header_start);
6406         header->pesig [0] = 'P';
6407         header->pesig [1] = 'E';
6408         
6409         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6410         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6411         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6412         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6413         if (assemblyb->pekind == 1) {
6414                 /* it's a dll */
6415                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6416         } else {
6417                 /* it's an exe */
6418                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6419         }
6420
6421         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6422
6423         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6424         header->pe.pe_major = 6;
6425         header->pe.pe_minor = 0;
6426         size = assembly->sections [MONO_SECTION_TEXT].size;
6427         size += FILE_ALIGN - 1;
6428         size &= ~(FILE_ALIGN - 1);
6429         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6430         size = assembly->sections [MONO_SECTION_RSRC].size;
6431         size += FILE_ALIGN - 1;
6432         size &= ~(FILE_ALIGN - 1);
6433         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6434         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6435         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6436         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6437         /* pe_rva_entry_point always at the beginning of the text section */
6438         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6439
6440         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6441         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6442         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6443         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6444         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6445         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6446         size = section_start;
6447         size += FILE_ALIGN - 1;
6448         size &= ~(FILE_ALIGN - 1);
6449         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6450         size = image_size;
6451         size += VIRT_ALIGN - 1;
6452         size &= ~(VIRT_ALIGN - 1);
6453         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6454
6455         /*
6456         // Translate the PEFileKind value to the value expected by the Windows loader
6457         */
6458         {
6459                 short kind;
6460
6461                 /*
6462                 // PEFileKinds.Dll == 1
6463                 // PEFileKinds.ConsoleApplication == 2
6464                 // PEFileKinds.WindowApplication == 3
6465                 //
6466                 // need to get:
6467                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6468                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6469                 */
6470                 if (assemblyb->pekind == 3)
6471                         kind = 2;
6472                 else
6473                         kind = 3;
6474                 
6475                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6476         }    
6477         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6478         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6479         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6480         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6481         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6482         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6483
6484         /* fill data directory entries */
6485
6486         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6487         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6488
6489         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6490         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6491
6492         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6493         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6494         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6495         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6496         /* patch entrypoint name */
6497         if (assemblyb->pekind == 1)
6498                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6499         else
6500                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6501         /* patch imported function RVA name */
6502         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6503         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6504
6505         /* the import table */
6506         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6507         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6508         /* patch imported dll RVA name and other entries in the dir */
6509         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6510         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6511         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6512         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6513         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6514         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6515
6516         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6517         value = (assembly->text_rva + assembly->imp_names_offset);
6518         *p++ = (value) & 0xff;
6519         *p++ = (value >> 8) & (0xff);
6520         *p++ = (value >> 16) & (0xff);
6521         *p++ = (value >> 24) & (0xff);
6522
6523         /* the CLI header info */
6524         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6525         cli_header->ch_size = GUINT32_FROM_LE (72);
6526         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6527         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6528         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6529         if (assemblyb->entry_point) {
6530                 guint32 table_idx = 0;
6531                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6532                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6533                         table_idx = methodb->table_idx;
6534                 } else {
6535                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6536                 }
6537                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6538         } else {
6539                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6540         }
6541         /* The embedded managed resources */
6542         text_offset = assembly->text_rva + assembly->code.index;
6543         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6544         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6545         text_offset += assembly->resources.index;
6546         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6547         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6548         text_offset += assembly->meta_size;
6549         if (assembly->strong_name_size) {
6550                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6551                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6552                 text_offset += assembly->strong_name_size;
6553         }
6554
6555         /* write the section tables and section content */
6556         section = (MonoSectionTable*)(pefile->data + section_start);
6557         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558                 static const char section_names [][7] = {
6559                         ".text", ".rsrc", ".reloc"
6560                 };
6561                 if (!assembly->sections [i].size)
6562                         continue;
6563                 strcpy (section->st_name, section_names [i]);
6564                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6565                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6566                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6567                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6568                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6569                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6570                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6571                 section ++;
6572         }
6573         
6574         checked_write_file (file, pefile->data, pefile->index);
6575         
6576         mono_dynamic_stream_reset (pefile);
6577         
6578         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6579                 if (!assembly->sections [i].size)
6580                         continue;
6581                 
6582                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6583                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6584                 
6585                 switch (i) {
6586                 case MONO_SECTION_TEXT:
6587                         /* patch entry point */
6588                         p = (guchar*)(assembly->code.data + 2);
6589                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6590                         *p++ = (value) & 0xff;
6591                         *p++ = (value >> 8) & 0xff;
6592                         *p++ = (value >> 16) & 0xff;
6593                         *p++ = (value >> 24) & 0xff;
6594                 
6595                         checked_write_file (file, assembly->code.data, assembly->code.index);
6596                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6597                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6598                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6599                                 
6600
6601                         g_free (assembly->image.raw_metadata);
6602                         break;
6603                 case MONO_SECTION_RELOC: {
6604                         struct {
6605                                 guint32 page_rva;
6606                                 guint32 block_size;
6607                                 guint16 type_and_offset;
6608                                 guint16 term;
6609                         } reloc;
6610                         
6611                         g_assert (sizeof (reloc) == 12);
6612                         
6613                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6614                         reloc.block_size = GUINT32_FROM_LE (12);
6615                         
6616                         /* 
6617                          * the entrypoint is always at the start of the text section 
6618                          * 3 is IMAGE_REL_BASED_HIGHLOW
6619                          * 2 is patch_size_rva - text_rva
6620                          */
6621                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6622                         reloc.term = 0;
6623                         
6624                         checked_write_file (file, &reloc, sizeof (reloc));
6625                         
6626                         break;
6627                 }
6628                 case MONO_SECTION_RSRC:
6629                         if (assembly->win32_res) {
6630
6631                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6632                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6633                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6634                         }
6635                         break;
6636                 default:
6637                         g_assert_not_reached ();
6638                 }
6639         }
6640         
6641         /* check that the file is properly padded */
6642         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6643                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6644         if (! SetEndOfFile (file))
6645                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6646         
6647         mono_dynamic_stream_reset (&assembly->code);
6648         mono_dynamic_stream_reset (&assembly->us);
6649         mono_dynamic_stream_reset (&assembly->blob);
6650         mono_dynamic_stream_reset (&assembly->guid);
6651         mono_dynamic_stream_reset (&assembly->sheap);
6652
6653         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6654         g_hash_table_destroy (assembly->blob_cache);
6655         assembly->blob_cache = NULL;
6656
6657         return TRUE;
6658 }
6659
6660 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6661
6662 gboolean
6663 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6664 {
6665         g_assert_not_reached ();
6666 }
6667
6668 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6669
6670 #ifndef DISABLE_REFLECTION_EMIT
6671
6672 MonoReflectionModule *
6673 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6674 {
6675         char *name;
6676         MonoImage *image;
6677         MonoImageOpenStatus status;
6678         MonoDynamicAssembly *assembly;
6679         guint32 module_count;
6680         MonoImage **new_modules;
6681         gboolean *new_modules_loaded;
6682         
6683         mono_error_init (error);
6684         
6685         name = mono_string_to_utf8 (fileName);
6686
6687         image = mono_image_open (name, &status);
6688         if (!image) {
6689                 if (status == MONO_IMAGE_ERROR_ERRNO)
6690                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6691                 else
6692                         mono_error_set_bad_image_name (error, name, NULL);
6693                 g_free (name);
6694                 return NULL;
6695         }
6696
6697         g_free (name);
6698
6699         assembly = ab->dynamic_assembly;
6700         image->assembly = (MonoAssembly*)assembly;
6701
6702         module_count = image->assembly->image->module_count;
6703         new_modules = g_new0 (MonoImage *, module_count + 1);
6704         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6705
6706         if (image->assembly->image->modules)
6707                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6708         if (image->assembly->image->modules_loaded)
6709                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6710         new_modules [module_count] = image;
6711         new_modules_loaded [module_count] = TRUE;
6712         mono_image_addref (image);
6713
6714         g_free (image->assembly->image->modules);
6715         image->assembly->image->modules = new_modules;
6716         image->assembly->image->modules_loaded = new_modules_loaded;
6717         image->assembly->image->module_count ++;
6718
6719         mono_assembly_load_references (image, &status);
6720         if (status) {
6721                 mono_image_close (image);
6722                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6723                 return NULL;
6724         }
6725
6726         return mono_module_get_object_checked (mono_domain_get (), image, error);
6727 }
6728
6729 #endif /* DISABLE_REFLECTION_EMIT */
6730
6731 /*
6732  * We need to return always the same object for MethodInfo, FieldInfo etc..
6733  * but we need to consider the reflected type.
6734  * type uses a different hash, since it uses custom hash/equal functions.
6735  */
6736
6737 typedef struct {
6738         gpointer item;
6739         MonoClass *refclass;
6740 } ReflectedEntry;
6741
6742 static gboolean
6743 reflected_equal (gconstpointer a, gconstpointer b) {
6744         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6745         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6746
6747         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6748 }
6749
6750 static guint
6751 reflected_hash (gconstpointer a) {
6752         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6753         return mono_aligned_addr_hash (ea->item);
6754 }
6755
6756 #define CHECK_OBJECT(t,p,k)     \
6757         do {    \
6758                 t _obj; \
6759                 ReflectedEntry e;       \
6760                 e.item = (p);   \
6761                 e.refclass = (k);       \
6762                 mono_domain_lock (domain);      \
6763                 if (!domain->refobject_hash)    \
6764                         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");  \
6765                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6766                         mono_domain_unlock (domain);    \
6767                         return _obj;    \
6768                 }       \
6769         mono_domain_unlock (domain); \
6770         } while (0)
6771
6772 #ifdef HAVE_BOEHM_GC
6773 /* ReflectedEntry doesn't need to be GC tracked */
6774 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6775 #define FREE_REFENTRY(entry) g_free ((entry))
6776 #define REFENTRY_REQUIRES_CLEANUP
6777 #else
6778 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6779 /* FIXME: */
6780 #define FREE_REFENTRY(entry)
6781 #endif
6782
6783 #define CACHE_OBJECT(t,p,o,k)   \
6784         do {    \
6785                 t _obj; \
6786         ReflectedEntry pe; \
6787         pe.item = (p); \
6788         pe.refclass = (k); \
6789         mono_domain_lock (domain); \
6790                 if (!domain->refobject_hash)    \
6791                         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");  \
6792         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6793         if (!_obj) { \
6794                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6795                     e->item = (p);      \
6796                     e->refclass = (k);  \
6797                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6798             _obj = o; \
6799         } \
6800                 mono_domain_unlock (domain);    \
6801         return _obj; \
6802         } while (0)
6803
6804 static void
6805 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6806 {
6807         mono_domain_lock (domain);
6808         if (domain->refobject_hash) {
6809         ReflectedEntry pe;
6810                 gpointer orig_pe, orig_value;
6811
6812                 pe.item = o;
6813                 pe.refclass = klass;
6814                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6815                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6816                         FREE_REFENTRY (orig_pe);
6817                 }
6818         }
6819         mono_domain_unlock (domain);
6820 }
6821
6822 #ifdef REFENTRY_REQUIRES_CLEANUP
6823 static void
6824 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6825 {
6826         FREE_REFENTRY (key);
6827 }
6828 #endif
6829
6830 void
6831 mono_reflection_cleanup_domain (MonoDomain *domain)
6832 {
6833         if (domain->refobject_hash) {
6834 /*let's avoid scanning the whole hashtable if not needed*/
6835 #ifdef REFENTRY_REQUIRES_CLEANUP
6836                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6837 #endif
6838                 mono_g_hash_table_destroy (domain->refobject_hash);
6839                 domain->refobject_hash = NULL;
6840         }
6841 }
6842
6843 #ifndef DISABLE_REFLECTION_EMIT
6844 static gpointer
6845 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6846 {
6847         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6848 }
6849
6850 static gpointer
6851 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6852 {
6853         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6854 }
6855
6856 void
6857 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6858 {
6859         MonoDynamicImage *image = moduleb->dynamic_image;
6860         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6861         if (!image) {
6862                 MonoError error;
6863                 int module_count;
6864                 MonoImage **new_modules;
6865                 MonoImage *ass;
6866                 char *name, *fqname;
6867                 /*
6868                  * FIXME: we already created an image in mono_image_basic_init (), but
6869                  * we don't know which module it belongs to, since that is only 
6870                  * determined at assembly save time.
6871                  */
6872                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6873                 name = mono_string_to_utf8 (ab->name);
6874                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6875                 if (!mono_error_ok (&error)) {
6876                         g_free (name);
6877                         mono_error_raise_exception (&error);
6878                 }
6879                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6880
6881                 moduleb->module.image = &image->image;
6882                 moduleb->dynamic_image = image;
6883                 register_module (mono_object_domain (moduleb), moduleb, image);
6884
6885                 /* register the module with the assembly */
6886                 ass = ab->dynamic_assembly->assembly.image;
6887                 module_count = ass->module_count;
6888                 new_modules = g_new0 (MonoImage *, module_count + 1);
6889
6890                 if (ass->modules)
6891                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6892                 new_modules [module_count] = &image->image;
6893                 mono_image_addref (&image->image);
6894
6895                 g_free (ass->modules);
6896                 ass->modules = new_modules;
6897                 ass->module_count ++;
6898         }
6899 }
6900
6901 void
6902 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6903 {
6904         MonoDynamicImage *image = moduleb->dynamic_image;
6905
6906         g_assert (type->type);
6907         image->wrappers_type = mono_class_from_mono_type (type->type);
6908 }
6909
6910 #endif
6911
6912 /*
6913  * mono_assembly_get_object:
6914  * @domain: an app domain
6915  * @assembly: an assembly
6916  *
6917  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6918  */
6919 MonoReflectionAssembly*
6920 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6921 {
6922         MonoError error;
6923         MonoReflectionAssembly *result;
6924         result = mono_assembly_get_object_checked (domain, assembly, &error);
6925         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6926         return result;
6927 }
6928 /*
6929  * mono_assembly_get_object_checked:
6930  * @domain: an app domain
6931  * @assembly: an assembly
6932  *
6933  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6934  */
6935 MonoReflectionAssembly*
6936 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6937 {
6938         MonoReflectionAssembly *res;
6939         
6940         mono_error_init (error);
6941
6942         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6943         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6944         if (!res)
6945                 return NULL;
6946         res->assembly = assembly;
6947
6948         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6949 }
6950
6951
6952
6953 MonoReflectionModule*   
6954 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6955 {
6956         MonoError error;
6957         MonoReflectionModule *result;
6958         result = mono_module_get_object_checked (domain, image, &error);
6959         mono_error_raise_exception (&error);
6960         return result;
6961 }
6962
6963 MonoReflectionModule*
6964 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6965 {
6966         MonoReflectionModule *res;
6967         char* basename;
6968         
6969         mono_error_init (error);
6970         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6971         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6972         if (!res)
6973                 return NULL;
6974
6975         res->image = image;
6976         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6977         if (!assm_obj)
6978                 return NULL;
6979         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6980
6981         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6982         basename = g_path_get_basename (image->name);
6983         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6984         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6985         
6986         g_free (basename);
6987
6988         if (image->assembly->image == image) {
6989                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6990         } else {
6991                 int i;
6992                 res->token = 0;
6993                 if (image->assembly->image->modules) {
6994                         for (i = 0; i < image->assembly->image->module_count; i++) {
6995                                 if (image->assembly->image->modules [i] == image)
6996                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6997                         }
6998                         g_assert (res->token);
6999                 }
7000         }
7001
7002         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7003 }
7004
7005 MonoReflectionModule*
7006 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7007 {
7008         MonoError error;
7009         MonoReflectionModule *result;
7010         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7011         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7012         return result;
7013 }
7014
7015 MonoReflectionModule*
7016 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7017 {
7018         MonoReflectionModule *res;
7019         MonoTableInfo *table;
7020         guint32 cols [MONO_FILE_SIZE];
7021         const char *name;
7022         guint32 i, name_idx;
7023         const char *val;
7024         
7025         mono_error_init (error);
7026
7027         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7028         if (!res)
7029                 return NULL;
7030
7031         table = &image->tables [MONO_TABLE_FILE];
7032         g_assert (table_index < table->rows);
7033         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7034
7035         res->image = NULL;
7036         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7037         if (!assm_obj)
7038                 return NULL;
7039         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7040         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7041
7042         /* Check whenever the row has a corresponding row in the moduleref table */
7043         table = &image->tables [MONO_TABLE_MODULEREF];
7044         for (i = 0; i < table->rows; ++i) {
7045                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7046                 val = mono_metadata_string_heap (image, name_idx);
7047                 if (strcmp (val, name) == 0)
7048                         res->image = image->modules [i];
7049         }
7050
7051         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7052         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7053         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7054         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7055         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7056
7057         return res;
7058 }
7059
7060 static gboolean
7061 verify_safe_for_managed_space (MonoType *type)
7062 {
7063         switch (type->type) {
7064 #ifdef DEBUG_HARDER
7065         case MONO_TYPE_ARRAY:
7066                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7067         case MONO_TYPE_PTR:
7068                 return verify_safe_for_managed_space (type->data.type);
7069         case MONO_TYPE_SZARRAY:
7070                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7071         case MONO_TYPE_GENERICINST: {
7072                 MonoGenericInst *inst = type->data.generic_class->inst;
7073                 int i;
7074                 if (!inst->is_open)
7075                         break;
7076                 for (i = 0; i < inst->type_argc; ++i)
7077                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7078                                 return FALSE;
7079                 return TRUE;
7080         }
7081 #endif
7082         case MONO_TYPE_VAR:
7083         case MONO_TYPE_MVAR:
7084                 return TRUE;
7085         default:
7086                 return TRUE;
7087         }
7088 }
7089
7090 static MonoType*
7091 mono_type_normalize (MonoType *type)
7092 {
7093         int i;
7094         MonoGenericClass *gclass;
7095         MonoGenericInst *ginst;
7096         MonoClass *gtd;
7097         MonoGenericContainer *gcontainer;
7098         MonoType **argv = NULL;
7099         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7100
7101         if (type->type != MONO_TYPE_GENERICINST)
7102                 return type;
7103
7104         gclass = type->data.generic_class;
7105         ginst = gclass->context.class_inst;
7106         if (!ginst->is_open)
7107                 return type;
7108
7109         gtd = gclass->container_class;
7110         gcontainer = gtd->generic_container;
7111         argv = g_newa (MonoType*, ginst->type_argc);
7112
7113         for (i = 0; i < ginst->type_argc; ++i) {
7114                 MonoType *t = ginst->type_argv [i], *norm;
7115                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7116                         is_denorm_gtd = FALSE;
7117                 norm = mono_type_normalize (t);
7118                 argv [i] = norm;
7119                 if (norm != t)
7120                         requires_rebind = TRUE;
7121         }
7122
7123         if (is_denorm_gtd)
7124                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7125
7126         if (requires_rebind) {
7127                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7128                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7129         }
7130
7131         return type;
7132 }
7133 /*
7134  * mono_type_get_object:
7135  * @domain: an app domain
7136  * @type: a type
7137  *
7138  * Return an System.MonoType object representing the type @type.
7139  */
7140 MonoReflectionType*
7141 mono_type_get_object (MonoDomain *domain, MonoType *type)
7142 {
7143         MonoError error;
7144         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7145         mono_error_raise_exception (&error);
7146
7147         return ret;
7148 }
7149
7150 MonoReflectionType*
7151 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7152 {
7153         MonoType *norm_type;
7154         MonoReflectionType *res;
7155         MonoClass *klass;
7156
7157         mono_error_init (error);
7158
7159         klass = mono_class_from_mono_type (type);
7160
7161         /*we must avoid using @type as it might have come
7162          * from a mono_metadata_type_dup and the caller
7163          * expects that is can be freed.
7164          * Using the right type from 
7165          */
7166         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7167
7168         /* void is very common */
7169         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7170                 return (MonoReflectionType*)domain->typeof_void;
7171
7172         /*
7173          * If the vtable of the given class was already created, we can use
7174          * the MonoType from there and avoid all locking and hash table lookups.
7175          * 
7176          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7177          * that the resulting object is different.   
7178          */
7179         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7180                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7181                 if (vtable && vtable->type)
7182                         return (MonoReflectionType *)vtable->type;
7183         }
7184
7185         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7186         mono_domain_lock (domain);
7187         if (!domain->type_hash)
7188                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7189                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7190         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7191                 mono_domain_unlock (domain);
7192                 mono_loader_unlock ();
7193                 return res;
7194         }
7195
7196         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7197          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7198          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7199          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7200          * artifact of how generics are encoded and should be transparent to managed code so we
7201          * need to weed out this diference when retrieving managed System.Type objects.
7202          */
7203         norm_type = mono_type_normalize (type);
7204         if (norm_type != type) {
7205                 res = mono_type_get_object_checked (domain, norm_type, error);
7206                 if (!mono_error_ok (error))
7207                         return NULL;
7208                 mono_g_hash_table_insert (domain->type_hash, type, res);
7209                 mono_domain_unlock (domain);
7210                 mono_loader_unlock ();
7211                 return res;
7212         }
7213
7214         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7215         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7216                 g_assert (0);
7217
7218         if (!verify_safe_for_managed_space (type)) {
7219                 mono_domain_unlock (domain);
7220                 mono_loader_unlock ();
7221                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7222                 return NULL;
7223         }
7224
7225         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7226                 gboolean is_type_done = TRUE;
7227                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7228                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7229                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7230                 */
7231                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7232                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7233
7234                         if (gparam->owner && gparam->owner->is_method) {
7235                                 MonoMethod *method = gparam->owner->owner.method;
7236                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7237                                         is_type_done = FALSE;
7238                         } else if (gparam->owner && !gparam->owner->is_method) {
7239                                 MonoClass *klass = gparam->owner->owner.klass;
7240                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7241                                         is_type_done = FALSE;
7242                         }
7243                 } 
7244
7245                 /* g_assert_not_reached (); */
7246                 /* should this be considered an error condition? */
7247                 if (is_type_done && !type->byref) {
7248                         mono_domain_unlock (domain);
7249                         mono_loader_unlock ();
7250                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7251                 }
7252         }
7253         /* This is stored in vtables/JITted code so it has to be pinned */
7254         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7255         if (!mono_error_ok (error))
7256                 return NULL;
7257
7258         res->type = type;
7259         mono_g_hash_table_insert (domain->type_hash, type, res);
7260
7261         if (type->type == MONO_TYPE_VOID)
7262                 domain->typeof_void = (MonoObject*)res;
7263
7264         mono_domain_unlock (domain);
7265         mono_loader_unlock ();
7266         return res;
7267 }
7268
7269 /*
7270  * mono_method_get_object:
7271  * @domain: an app domain
7272  * @method: a method
7273  * @refclass: the reflected type (can be NULL)
7274  *
7275  * Return an System.Reflection.MonoMethod object representing the method @method.
7276  */
7277 MonoReflectionMethod*
7278 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7279 {
7280         MonoError error;
7281         MonoReflectionMethod *ret = NULL;
7282         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7283         mono_error_raise_exception (&error);
7284         return ret;
7285 }
7286
7287 /*
7288  * mono_method_get_object_checked:
7289  * @domain: an app domain
7290  * @method: a method
7291  * @refclass: the reflected type (can be NULL)
7292  * @error: set on error.
7293  *
7294  * Return an System.Reflection.MonoMethod object representing the method @method.
7295  * Returns NULL and sets @error on error.
7296  */
7297 MonoReflectionMethod*
7298 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7299 {
7300         /*
7301          * We use the same C representation for methods and constructors, but the type 
7302          * name in C# is different.
7303          */
7304         MonoReflectionType *rt;
7305         MonoClass *klass;
7306         MonoReflectionMethod *ret;
7307
7308         mono_error_init (error);
7309
7310         if (method->is_inflated) {
7311                 MonoReflectionGenericMethod *gret;
7312
7313                 if (!refclass)
7314                         refclass = method->klass;
7315                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7316                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7317                         klass = mono_class_get_mono_generic_cmethod_class ();
7318                 } else {
7319                         klass = mono_class_get_mono_generic_method_class ();
7320                 }
7321                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7322                 if (!mono_error_ok (error))
7323                         goto leave;
7324                 gret->method.method = method;
7325
7326                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7327
7328                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7329                 if (!mono_error_ok (error))
7330                     goto leave;
7331
7332                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7333
7334                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7335         }
7336
7337         if (!refclass)
7338                 refclass = method->klass;
7339
7340         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7341         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7342                 klass = mono_class_get_mono_cmethod_class ();
7343         }
7344         else {
7345                 klass = mono_class_get_mono_method_class ();
7346         }
7347         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7348         if (!mono_error_ok (error))
7349                 goto leave;
7350         ret->method = method;
7351
7352         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7353         if (!mono_error_ok (error))
7354                 goto leave;
7355
7356         MONO_OBJECT_SETREF (ret, reftype, rt);
7357
7358         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7359
7360 leave:
7361         g_assert (!mono_error_ok (error));
7362         return NULL;
7363 }
7364
7365 /*
7366  * mono_method_clear_object:
7367  *
7368  *   Clear the cached reflection objects for the dynamic method METHOD.
7369  */
7370 void
7371 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7372 {
7373         MonoClass *klass;
7374         g_assert (method_is_dynamic (method));
7375
7376         klass = method->klass;
7377         while (klass) {
7378                 clear_cached_object (domain, method, klass);
7379                 klass = klass->parent;
7380         }
7381         /* Added by mono_param_get_objects () */
7382         clear_cached_object (domain, &(method->signature), NULL);
7383         klass = method->klass;
7384         while (klass) {
7385                 clear_cached_object (domain, &(method->signature), klass);
7386                 klass = klass->parent;
7387         }
7388 }
7389
7390 /*
7391  * mono_field_get_object:
7392  * @domain: an app domain
7393  * @klass: a type
7394  * @field: a field
7395  *
7396  * Return an System.Reflection.MonoField object representing the field @field
7397  * in class @klass.
7398  */
7399 MonoReflectionField*
7400 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7401 {
7402         MonoError error;
7403         MonoReflectionField *result;
7404         result = mono_field_get_object_checked (domain, klass, field, &error);
7405         mono_error_raise_exception (&error);
7406         return result;
7407 }
7408
7409 /*
7410  * mono_field_get_object_checked:
7411  * @domain: an app domain
7412  * @klass: a type
7413  * @field: a field
7414  * @error: set on error
7415  *
7416  * Return an System.Reflection.MonoField object representing the field @field
7417  * in class @klass. On error, returns NULL and sets @error.
7418  */
7419 MonoReflectionField*
7420 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7421 {
7422         MonoReflectionType *rt;
7423         MonoReflectionField *res;
7424
7425         mono_error_init (error);
7426
7427         CHECK_OBJECT (MonoReflectionField *, field, klass);
7428         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7429         if (!res)
7430                 return NULL;
7431         res->klass = klass;
7432         res->field = field;
7433         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7434
7435         if (is_field_on_inst (field)) {
7436                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7437
7438                 rt = mono_type_get_object_checked (domain, field->type, error);
7439                 if (!mono_error_ok (error))
7440                         return NULL;
7441
7442                 MONO_OBJECT_SETREF (res, type, rt);
7443         } else {
7444                 if (field->type) {
7445                         rt = mono_type_get_object_checked (domain, field->type, error);
7446                         if (!mono_error_ok (error))
7447                                 return NULL;
7448
7449                         MONO_OBJECT_SETREF (res, type, rt);
7450                 }
7451                 res->attrs = mono_field_get_flags (field);
7452         }
7453         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7454 }
7455
7456 /*
7457  * mono_property_get_object:
7458  * @domain: an app domain
7459  * @klass: a type
7460  * @property: a property
7461  *
7462  * Return an System.Reflection.MonoProperty object representing the property @property
7463  * in class @klass.
7464  */
7465 MonoReflectionProperty*
7466 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7467 {
7468         MonoError error;
7469         MonoReflectionProperty *result;
7470         result = mono_property_get_object_checked (domain, klass, property, &error);
7471         mono_error_raise_exception (&error);
7472         return result;
7473 }
7474
7475 /**
7476  * mono_property_get_object:
7477  * @domain: an app domain
7478  * @klass: a type
7479  * @property: a property
7480  * @error: set on error
7481  *
7482  * Return an System.Reflection.MonoProperty object representing the property @property
7483  * in class @klass.  On error returns NULL and sets @error.
7484  */
7485 MonoReflectionProperty*
7486 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7487 {
7488         MonoReflectionProperty *res;
7489
7490         mono_error_init (error);
7491
7492         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7493         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7494         if (!res)
7495                 return NULL;
7496         res->klass = klass;
7497         res->property = property;
7498         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7499 }
7500
7501 /*
7502  * mono_event_get_object:
7503  * @domain: an app domain
7504  * @klass: a type
7505  * @event: a event
7506  *
7507  * Return an System.Reflection.MonoEvent object representing the event @event
7508  * in class @klass.
7509  */
7510 MonoReflectionEvent*
7511 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7512 {
7513         MonoError error;
7514         MonoReflectionEvent *result;
7515         result = mono_event_get_object_checked (domain, klass, event, &error);
7516         mono_error_raise_exception (&error);
7517         return result;
7518 }
7519
7520 /**
7521  * mono_event_get_object_checked:
7522  * @domain: an app domain
7523  * @klass: a type
7524  * @event: a event
7525  * @error: set on error
7526  *
7527  * Return an System.Reflection.MonoEvent object representing the event @event
7528  * in class @klass. On failure sets @error and returns NULL
7529  */
7530 MonoReflectionEvent*
7531 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7532 {
7533         MonoReflectionEvent *res;
7534         MonoReflectionMonoEvent *mono_event;
7535
7536         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7537         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7538         if (!mono_event)
7539                 return NULL;
7540         mono_event->klass = klass;
7541         mono_event->event = event;
7542         res = (MonoReflectionEvent*)mono_event;
7543         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7544 }
7545
7546 /**
7547  * mono_get_reflection_missing_object:
7548  * @domain: Domain where the object lives
7549  *
7550  * Returns the System.Reflection.Missing.Value singleton object
7551  * (of type System.Reflection.Missing).
7552  *
7553  * Used as the value for ParameterInfo.DefaultValue when Optional
7554  * is present
7555  */
7556 static MonoObject *
7557 mono_get_reflection_missing_object (MonoDomain *domain)
7558 {
7559         MonoError error;
7560         MonoObject *obj;
7561         static MonoClassField *missing_value_field = NULL;
7562         
7563         if (!missing_value_field) {
7564                 MonoClass *missing_klass;
7565                 missing_klass = mono_class_get_missing_class ();
7566                 mono_class_init (missing_klass);
7567                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7568                 g_assert (missing_value_field);
7569         }
7570         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7571         mono_error_assert_ok (&error);
7572         return obj;
7573 }
7574
7575 static MonoObject*
7576 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7577 {
7578         if (!*dbnull)
7579                 *dbnull = mono_get_dbnull_object (domain);
7580         return *dbnull;
7581 }
7582
7583 static MonoObject*
7584 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7585 {
7586         if (!*reflection_missing)
7587                 *reflection_missing = mono_get_reflection_missing_object (domain);
7588         return *reflection_missing;
7589 }
7590
7591 /*
7592  * mono_param_get_objects:
7593  * @domain: an app domain
7594  * @method: a method
7595  *
7596  * Return an System.Reflection.ParameterInfo array object representing the parameters
7597  * in the method @method.
7598  */
7599 MonoArray*
7600 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7601 {
7602         static MonoClass *System_Reflection_ParameterInfo;
7603         static MonoClass *System_Reflection_ParameterInfo_array;
7604         MonoArray *res = NULL;
7605         MonoReflectionMethod *member = NULL;
7606         MonoReflectionParameter *param = NULL;
7607         char **names = NULL, **blobs = NULL;
7608         guint32 *types = NULL;
7609         MonoType *type = NULL;
7610         MonoObject *dbnull = NULL;
7611         MonoObject *missing = NULL;
7612         MonoMarshalSpec **mspecs = NULL;
7613         MonoMethodSignature *sig = NULL;
7614         MonoVTable *pinfo_vtable;
7615         MonoReflectionType *rt;
7616         int i;
7617
7618         mono_error_init (error);
7619         
7620         if (!System_Reflection_ParameterInfo_array) {
7621                 MonoClass *klass;
7622
7623                 klass = mono_class_get_mono_parameter_info_class ();
7624
7625                 mono_memory_barrier ();
7626                 System_Reflection_ParameterInfo = klass; 
7627
7628         
7629                 klass = mono_array_class_get (klass, 1);
7630                 mono_memory_barrier ();
7631                 System_Reflection_ParameterInfo_array = klass;
7632         }
7633
7634         sig = mono_method_signature_checked (method, error);
7635         if (!mono_error_ok (error))
7636                 goto leave;
7637
7638         if (!sig->param_count) {
7639                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7640                 if (!res)
7641                         goto leave;
7642
7643                 return res;
7644         }
7645
7646         /* Note: the cache is based on the address of the signature into the method
7647          * since we already cache MethodInfos with the method as keys.
7648          */
7649         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7650
7651         member = mono_method_get_object_checked (domain, method, refclass, error);
7652         if (!member)
7653                 goto leave;
7654         names = g_new (char *, sig->param_count);
7655         mono_method_get_param_names (method, (const char **) names);
7656
7657         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7658         mono_method_get_marshal_info (method, mspecs);
7659
7660         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7661         if (!res)
7662                 goto leave;
7663
7664         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7665         for (i = 0; i < sig->param_count; ++i) {
7666                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7667                 if (!param)
7668                         goto leave;
7669
7670                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7671                 if (!rt)
7672                         goto leave;
7673
7674                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7675
7676                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7677
7678                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7679
7680                 param->PositionImpl = i;
7681                 param->AttrsImpl = sig->params [i]->attrs;
7682
7683                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7684                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7685                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7686                         else
7687                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7688                 } else {
7689
7690                         if (!blobs) {
7691                                 blobs = g_new0 (char *, sig->param_count);
7692                                 types = g_new0 (guint32, sig->param_count);
7693                                 get_default_param_value_blobs (method, blobs, types); 
7694                         }
7695
7696                         /* Build MonoType for the type from the Constant Table */
7697                         if (!type)
7698                                 type = g_new0 (MonoType, 1);
7699                         type->type = (MonoTypeEnum)types [i];
7700                         type->data.klass = NULL;
7701                         if (types [i] == MONO_TYPE_CLASS)
7702                                 type->data.klass = mono_defaults.object_class;
7703                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7704                                 /* For enums, types [i] contains the base type */
7705
7706                                         type->type = MONO_TYPE_VALUETYPE;
7707                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7708                         } else
7709                                 type->data.klass = mono_class_from_mono_type (type);
7710
7711                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7712                         if (!is_ok (error))
7713                                 goto leave;
7714                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7715
7716                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7717                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7718                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7719                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7720                                 else
7721                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7722                         }
7723                         
7724                 }
7725
7726                 if (mspecs [i + 1]) {
7727                         MonoReflectionMarshalAsAttribute* mobj;
7728                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7729                         if (!mobj)
7730                                 goto leave;
7731                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7732                 }
7733                 
7734                 mono_array_setref (res, i, param);
7735         }
7736
7737 leave:
7738         g_free (names);
7739         g_free (blobs);
7740         g_free (types);
7741         g_free (type);
7742
7743         if (sig) {
7744                 for (i = sig->param_count; i >= 0; i--) {
7745                         if (mspecs [i])
7746                                 mono_metadata_free_marshal_spec (mspecs [i]);
7747                 }
7748         }
7749         g_free (mspecs);
7750
7751         if (!is_ok (error))
7752                 return NULL;
7753         
7754         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7755 }
7756
7757 MonoArray*
7758 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7759 {
7760         MonoError error;
7761         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7762         mono_error_assert_ok (&error);
7763         return result;
7764 }
7765
7766 /*
7767  * mono_method_body_get_object:
7768  * @domain: an app domain
7769  * @method: a method
7770  *
7771  * Return an System.Reflection.MethodBody object representing the method @method.
7772  */
7773 MonoReflectionMethodBody*
7774 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7775 {
7776         MonoError error;
7777         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7778         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7779         return result;
7780 }
7781
7782 /**
7783  * mono_method_body_get_object_checked:
7784  * @domain: an app domain
7785  * @method: a method
7786  * @error: set on error
7787  *
7788  * Return an System.Reflection.MethodBody object representing the
7789  * method @method.  On failure, returns NULL and sets @error.
7790  */
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7793 {
7794         MonoReflectionMethodBody *ret;
7795         MonoMethodHeader *header;
7796         MonoImage *image;
7797         MonoReflectionType *rt;
7798         guint32 method_rva, local_var_sig_token;
7799         char *ptr;
7800         unsigned char format, flags;
7801         int i;
7802
7803         mono_error_init (error);
7804
7805         /* for compatibility with .net */
7806         if (method_is_dynamic (method)) {
7807                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7808                 return NULL;
7809         }
7810
7811         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7812
7813         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7814                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7815             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7816                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7817             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7818                 return NULL;
7819
7820         image = method->klass->image;
7821         header = mono_method_get_header_checked (method, error);
7822         return_val_if_nok (error, NULL);
7823
7824         if (!image_is_dynamic (image)) {
7825                 /* Obtain local vars signature token */
7826                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7827                 ptr = mono_image_rva_map (image, method_rva);
7828                 flags = *(const unsigned char *) ptr;
7829                 format = flags & METHOD_HEADER_FORMAT_MASK;
7830                 switch (format){
7831                 case METHOD_HEADER_TINY_FORMAT:
7832                         local_var_sig_token = 0;
7833                         break;
7834                 case METHOD_HEADER_FAT_FORMAT:
7835                         ptr += 2;
7836                         ptr += 2;
7837                         ptr += 4;
7838                         local_var_sig_token = read32 (ptr);
7839                         break;
7840                 default:
7841                         g_assert_not_reached ();
7842                 }
7843         } else
7844                 local_var_sig_token = 0; //FIXME
7845
7846         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7847         if (!is_ok (error))
7848                 goto fail;
7849
7850         ret->init_locals = header->init_locals;
7851         ret->max_stack = header->max_stack;
7852         ret->local_var_sig_token = local_var_sig_token;
7853         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7854         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7855
7856         /* Locals */
7857         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7858         for (i = 0; i < header->num_locals; ++i) {
7859                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7860                 if (!is_ok (error))
7861                         goto fail;
7862
7863                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7864                 if (!is_ok (error))
7865                         goto fail;
7866
7867                 MONO_OBJECT_SETREF (info, local_type, rt);
7868
7869                 info->is_pinned = header->locals [i]->pinned;
7870                 info->local_index = i;
7871                 mono_array_setref (ret->locals, i, info);
7872         }
7873
7874         /* Exceptions */
7875         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7876         for (i = 0; i < header->num_clauses; ++i) {
7877                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7878                 if (!is_ok (error))
7879                         goto fail;
7880                 MonoExceptionClause *clause = &header->clauses [i];
7881
7882                 info->flags = clause->flags;
7883                 info->try_offset = clause->try_offset;
7884                 info->try_length = clause->try_len;
7885                 info->handler_offset = clause->handler_offset;
7886                 info->handler_length = clause->handler_len;
7887                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7888                         info->filter_offset = clause->data.filter_offset;
7889                 else if (clause->data.catch_class) {
7890                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7891                         if (!is_ok (error))
7892                                 goto fail;
7893
7894                         MONO_OBJECT_SETREF (info, catch_type, rt);
7895                 }
7896
7897                 mono_array_setref (ret->clauses, i, info);
7898         }
7899
7900         mono_metadata_free_mh (header);
7901         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7902         return ret;
7903
7904 fail:
7905         mono_metadata_free_mh (header);
7906         return NULL;
7907 }
7908
7909 /**
7910  * mono_get_dbnull_object:
7911  * @domain: Domain where the object lives
7912  *
7913  * Returns the System.DBNull.Value singleton object
7914  *
7915  * Used as the value for ParameterInfo.DefaultValue 
7916  */
7917 MonoObject *
7918 mono_get_dbnull_object (MonoDomain *domain)
7919 {
7920         MonoError error;
7921         MonoObject *obj;
7922         static MonoClassField *dbnull_value_field = NULL;
7923         
7924         if (!dbnull_value_field) {
7925                 MonoClass *dbnull_klass;
7926                 dbnull_klass = mono_class_get_dbnull_class ();
7927                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7928                 g_assert (dbnull_value_field);
7929         }
7930         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7931         mono_error_assert_ok (&error);
7932         return obj;
7933 }
7934
7935 static void
7936 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7937 {
7938         guint32 param_index, i, lastp, crow = 0;
7939         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7940         gint32 idx;
7941
7942         MonoClass *klass = method->klass;
7943         MonoImage *image = klass->image;
7944         MonoMethodSignature *methodsig = mono_method_signature (method);
7945
7946         MonoTableInfo *constt;
7947         MonoTableInfo *methodt;
7948         MonoTableInfo *paramt;
7949
7950         if (!methodsig->param_count)
7951                 return;
7952
7953         mono_class_init (klass);
7954
7955         if (image_is_dynamic (klass->image)) {
7956                 MonoReflectionMethodAux *aux;
7957                 if (method->is_inflated)
7958                         method = ((MonoMethodInflated*)method)->declaring;
7959                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7960                 if (aux && aux->param_defaults) {
7961                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7962                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7963                 }
7964                 return;
7965         }
7966
7967         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7968         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7969         constt = &image->tables [MONO_TABLE_CONSTANT];
7970
7971         idx = mono_method_get_index (method) - 1;
7972         g_assert (idx != -1);
7973
7974         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7975         if (idx + 1 < methodt->rows)
7976                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7977         else
7978                 lastp = paramt->rows + 1;
7979
7980         for (i = param_index; i < lastp; ++i) {
7981                 guint32 paramseq;
7982
7983                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7984                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7985
7986                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7987                         continue;
7988
7989                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7990                 if (!crow) {
7991                         continue;
7992                 }
7993         
7994                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7995                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7996                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7997         }
7998
7999         return;
8000 }
8001
8002 MonoObject *
8003 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8004 {
8005         void *retval;
8006         MonoClass *klass;
8007         MonoObject *object;
8008         MonoType *basetype = type;
8009
8010         mono_error_init (error);
8011
8012         if (!blob)
8013                 return NULL;
8014         
8015         klass = mono_class_from_mono_type (type);
8016         if (klass->valuetype) {
8017                 object = mono_object_new_checked (domain, klass, error);
8018                 return_val_if_nok (error, NULL);
8019                 retval = ((gchar *) object + sizeof (MonoObject));
8020                 if (klass->enumtype)
8021                         basetype = mono_class_enum_basetype (klass);
8022         } else {
8023                 retval = &object;
8024         }
8025                         
8026         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
8027                 return object;
8028         else
8029                 return NULL;
8030 }
8031
8032 static int
8033 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8034         int found_sep;
8035         char *s;
8036         gboolean quoted = FALSE;
8037
8038         memset (assembly, 0, sizeof (MonoAssemblyName));
8039         assembly->culture = "";
8040         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8041
8042         if (*p == '"') {
8043                 quoted = TRUE;
8044                 p++;
8045         }
8046         assembly->name = p;
8047         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8048                 p++;
8049         if (quoted) {
8050                 if (*p != '"')
8051                         return 1;
8052                 *p = 0;
8053                 p++;
8054         }
8055         if (*p != ',')
8056                 return 1;
8057         *p = 0;
8058         /* Remove trailing whitespace */
8059         s = p - 1;
8060         while (*s && g_ascii_isspace (*s))
8061                 *s-- = 0;
8062         p ++;
8063         while (g_ascii_isspace (*p))
8064                 p++;
8065         while (*p) {
8066                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8067                         p += 8;
8068                         assembly->major = strtoul (p, &s, 10);
8069                         if (s == p || *s != '.')
8070                                 return 1;
8071                         p = ++s;
8072                         assembly->minor = strtoul (p, &s, 10);
8073                         if (s == p || *s != '.')
8074                                 return 1;
8075                         p = ++s;
8076                         assembly->build = strtoul (p, &s, 10);
8077                         if (s == p || *s != '.')
8078                                 return 1;
8079                         p = ++s;
8080                         assembly->revision = strtoul (p, &s, 10);
8081                         if (s == p)
8082                                 return 1;
8083                         p = s;
8084                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8085                         p += 8;
8086                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8087                                 assembly->culture = "";
8088                                 p += 7;
8089                         } else {
8090                                 assembly->culture = p;
8091                                 while (*p && *p != ',') {
8092                                         p++;
8093                                 }
8094                         }
8095                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8096                         p += 15;
8097                         if (strncmp (p, "null", 4) == 0) {
8098                                 p += 4;
8099                         } else {
8100                                 int len;
8101                                 gchar *start = p;
8102                                 while (*p && *p != ',') {
8103                                         p++;
8104                                 }
8105                                 len = (p - start + 1);
8106                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8107                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8108                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8109                         }
8110                 } else {
8111                         while (*p && *p != ',')
8112                                 p++;
8113                 }
8114                 found_sep = 0;
8115                 while (g_ascii_isspace (*p) || *p == ',') {
8116                         *p++ = 0;
8117                         found_sep = 1;
8118                         continue;
8119                 }
8120                 /* failed */
8121                 if (!found_sep)
8122                         return 1;
8123         }
8124
8125         return 0;
8126 }
8127
8128 /*
8129  * mono_reflection_parse_type:
8130  * @name: type name
8131  *
8132  * Parse a type name as accepted by the GetType () method and output the info
8133  * extracted in the info structure.
8134  * the name param will be mangled, so, make a copy before passing it to this function.
8135  * The fields in info will be valid until the memory pointed to by name is valid.
8136  *
8137  * See also mono_type_get_name () below.
8138  *
8139  * Returns: 0 on parse error.
8140  */
8141 static int
8142 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8143                              MonoTypeNameParse *info)
8144 {
8145         char *start, *p, *w, *last_point, *startn;
8146         int in_modifiers = 0;
8147         int isbyref = 0, rank = 0, isptr = 0;
8148
8149         start = p = w = name;
8150
8151         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8152         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8153         info->name = info->name_space = NULL;
8154         info->nested = NULL;
8155         info->modifiers = NULL;
8156         info->type_arguments = NULL;
8157
8158         /* last_point separates the namespace from the name */
8159         last_point = NULL;
8160         /* Skips spaces */
8161         while (*p == ' ') p++, start++, w++, name++;
8162
8163         while (*p) {
8164                 switch (*p) {
8165                 case '+':
8166                         *p = 0; /* NULL terminate the name */
8167                         startn = p + 1;
8168                         info->nested = g_list_append (info->nested, startn);
8169                         /* we have parsed the nesting namespace + name */
8170                         if (info->name)
8171                                 break;
8172                         if (last_point) {
8173                                 info->name_space = start;
8174                                 *last_point = 0;
8175                                 info->name = last_point + 1;
8176                         } else {
8177                                 info->name_space = (char *)"";
8178                                 info->name = start;
8179                         }
8180                         break;
8181                 case '.':
8182                         last_point = p;
8183                         break;
8184                 case '\\':
8185                         ++p;
8186                         break;
8187                 case '&':
8188                 case '*':
8189                 case '[':
8190                 case ',':
8191                 case ']':
8192                         in_modifiers = 1;
8193                         break;
8194                 default:
8195                         break;
8196                 }
8197                 if (in_modifiers)
8198                         break;
8199                 // *w++ = *p++;
8200                 p++;
8201         }
8202         
8203         if (!info->name) {
8204                 if (last_point) {
8205                         info->name_space = start;
8206                         *last_point = 0;
8207                         info->name = last_point + 1;
8208                 } else {
8209                         info->name_space = (char *)"";
8210                         info->name = start;
8211                 }
8212         }
8213         while (*p) {
8214                 switch (*p) {
8215                 case '&':
8216                         if (isbyref) /* only one level allowed by the spec */
8217                                 return 0;
8218                         isbyref = 1;
8219                         isptr = 0;
8220                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8221                         *p++ = 0;
8222                         break;
8223                 case '*':
8224                         if (isbyref) /* pointer to ref not okay */
8225                                 return 0;
8226                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8227                         isptr = 1;
8228                         *p++ = 0;
8229                         break;
8230                 case '[':
8231                         if (isbyref) /* array of ref and generic ref are not okay */
8232                                 return 0;
8233                         //Decide if it's an array of a generic argument list
8234                         *p++ = 0;
8235
8236                         if (!*p) //XXX test
8237                                 return 0;
8238                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8239                                 isptr = 0;
8240                                 rank = 1;
8241                                 while (*p) {
8242                                         if (*p == ']')
8243                                                 break;
8244                                         if (*p == ',')
8245                                                 rank++;
8246                                         else if (*p == '*') /* '*' means unknown lower bound */
8247                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8248                                         else
8249                                                 return 0;
8250                                         ++p;
8251                                 }
8252                                 if (*p++ != ']')
8253                                         return 0;
8254                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8255                         } else {
8256                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8257                                         return 0;
8258                                 isptr = 0;
8259                                 info->type_arguments = g_ptr_array_new ();
8260                                 while (*p) {
8261                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8262                                         gboolean fqname = FALSE;
8263
8264                                         g_ptr_array_add (info->type_arguments, subinfo);
8265
8266                                         while (*p == ' ') p++;
8267                                         if (*p == '[') {
8268                                                 p++;
8269                                                 fqname = TRUE;
8270                                         }
8271
8272                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8273                                                 return 0;
8274
8275                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8276                                         if (fqname && (*p != ']')) {
8277                                                 char *aname;
8278
8279                                                 if (*p != ',')
8280                                                         return 0;
8281                                                 *p++ = 0;
8282
8283                                                 aname = p;
8284                                                 while (*p && (*p != ']'))
8285                                                         p++;
8286
8287                                                 if (*p != ']')
8288                                                         return 0;
8289
8290                                                 *p++ = 0;
8291                                                 while (*aname) {
8292                                                         if (g_ascii_isspace (*aname)) {
8293                                                                 ++aname;
8294                                                                 continue;
8295                                                         }
8296                                                         break;
8297                                                 }
8298                                                 if (!*aname ||
8299                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8300                                                         return 0;
8301                                         } else if (fqname && (*p == ']')) {
8302                                                 *p++ = 0;
8303                                         }
8304                                         if (*p == ']') {
8305                                                 *p++ = 0;
8306                                                 break;
8307                                         } else if (!*p) {
8308                                                 return 0;
8309                                         }
8310                                         *p++ = 0;
8311                                 }
8312                         }
8313                         break;
8314                 case ']':
8315                         if (is_recursed)
8316                                 goto end;
8317                         return 0;
8318                 case ',':
8319                         if (is_recursed)
8320                                 goto end;
8321                         *p++ = 0;
8322                         while (*p) {
8323                                 if (g_ascii_isspace (*p)) {
8324                                         ++p;
8325                                         continue;
8326                                 }
8327                                 break;
8328                         }
8329                         if (!*p)
8330                                 return 0; /* missing assembly name */
8331                         if (!assembly_name_to_aname (&info->assembly, p))
8332                                 return 0;
8333                         break;
8334                 default:
8335                         return 0;
8336                 }
8337                 if (info->assembly.name)
8338                         break;
8339         }
8340         // *w = 0; /* terminate class name */
8341  end:
8342         if (!info->name || !*info->name)
8343                 return 0;
8344         if (endptr)
8345                 *endptr = p;
8346         /* add other consistency checks */
8347         return 1;
8348 }
8349
8350
8351 /**
8352  * mono_identifier_unescape_type_name_chars:
8353  * @identifier: the display name of a mono type
8354  *
8355  * Returns:
8356  *  The name in internal form, that is without escaping backslashes.
8357  *
8358  *  The string is modified in place!
8359  */
8360 char*
8361 mono_identifier_unescape_type_name_chars(char* identifier)
8362 {
8363         char *w, *r;
8364         if (!identifier)
8365                 return NULL;
8366         for (w = r = identifier; *r != 0; r++)
8367         {
8368                 char c = *r;
8369                 if (c == '\\') {
8370                         r++;
8371                         if (*r == 0)
8372                                 break;
8373                         c = *r;
8374                 }
8375                 *w = c;
8376                 w++;
8377         }
8378         if (w != r)
8379                 *w = 0;
8380         return identifier;
8381 }
8382
8383 void
8384 mono_identifier_unescape_info (MonoTypeNameParse* info);
8385
8386 static void
8387 unescape_each_type_argument(void* data, void* user_data)
8388 {
8389         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8390         mono_identifier_unescape_info (info);
8391 }
8392
8393 static void
8394 unescape_each_nested_name (void* data, void* user_data)
8395 {
8396         char* nested_name = (char*) data;
8397         mono_identifier_unescape_type_name_chars(nested_name);
8398 }
8399
8400 /**
8401  * mono_identifier_unescape_info:
8402  *
8403  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8404  *
8405  * Returns: nothing.
8406  *
8407  * Destructively updates the info by unescaping the identifiers that
8408  * comprise the type namespace, name, nested types (if any) and
8409  * generic type arguments (if any).
8410  *
8411  * The resulting info has the names in internal form.
8412  *
8413  */
8414 void
8415 mono_identifier_unescape_info (MonoTypeNameParse *info)
8416 {
8417         if (!info)
8418                 return;
8419         mono_identifier_unescape_type_name_chars(info->name_space);
8420         mono_identifier_unescape_type_name_chars(info->name);
8421         // but don't escape info->assembly
8422         if (info->type_arguments)
8423                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8424         if (info->nested)
8425                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8426 }
8427
8428 int
8429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8430 {
8431         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8432         if (ok) {
8433                 mono_identifier_unescape_info (info);
8434         }
8435         return ok;
8436 }
8437
8438 static MonoType*
8439 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8440 {
8441         gboolean type_resolve = FALSE;
8442         MonoType *type;
8443         MonoImage *rootimage = image;
8444
8445         mono_error_init (error);
8446
8447         if (info->assembly.name) {
8448                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8449                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8450                         /* 
8451                          * This could happen in the AOT compiler case when the search hook is not
8452                          * installed.
8453                          */
8454                         assembly = image->assembly;
8455                 if (!assembly) {
8456                         /* then we must load the assembly ourselve - see #60439 */
8457                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8458                         if (!assembly)
8459                                 return NULL;
8460                 }
8461                 image = assembly->image;
8462         } else if (!image) {
8463                 image = mono_defaults.corlib;
8464         }
8465
8466         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8467         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8468                 mono_error_cleanup (error);
8469                 image = mono_defaults.corlib;
8470                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8471         }
8472
8473         return type;
8474 }
8475
8476 /**
8477  * mono_reflection_get_type_internal:
8478  *
8479  * Returns: may return NULL on success, sets error on failure.
8480  */
8481 static MonoType*
8482 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8483 {
8484         MonoClass *klass;
8485         GList *mod;
8486         int modval;
8487         gboolean bounded = FALSE;
8488         
8489         mono_error_init (error);
8490         if (!image)
8491                 image = mono_defaults.corlib;
8492
8493         if (!rootimage)
8494                 rootimage = mono_defaults.corlib;
8495
8496         if (ignorecase)
8497                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8498         else
8499                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8500
8501         if (!klass)
8502                 return NULL;
8503
8504         for (mod = info->nested; mod; mod = mod->next) {
8505                 gpointer iter = NULL;
8506                 MonoClass *parent;
8507
8508                 parent = klass;
8509                 mono_class_init (parent);
8510
8511                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8512                         char *lastp;
8513                         char *nested_name, *nested_nspace;
8514                         gboolean match = TRUE;
8515
8516                         lastp = strrchr ((const char *)mod->data, '.');
8517                         if (lastp) {
8518                                 /* Nested classes can have namespaces */
8519                                 int nspace_len;
8520
8521                                 nested_name = g_strdup (lastp + 1);
8522                                 nspace_len = lastp - (char*)mod->data;
8523                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8524                                 memcpy (nested_nspace, mod->data, nspace_len);
8525                                 nested_nspace [nspace_len] = '\0';
8526
8527                         } else {
8528                                 nested_name = (char *)mod->data;
8529                                 nested_nspace = NULL;
8530                         }
8531
8532                         if (nested_nspace) {
8533                                 if (ignorecase) {
8534                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8535                                                 match = FALSE;
8536                                 } else {
8537                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8538                                                 match = FALSE;
8539                                 }
8540                         }
8541                         if (match) {
8542                                 if (ignorecase) {
8543                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8544                                                 match = FALSE;
8545                                 } else {
8546                                         if (strcmp (klass->name, nested_name) != 0)
8547                                                 match = FALSE;
8548                                 }
8549                         }
8550                         if (lastp) {
8551                                 g_free (nested_name);
8552                                 g_free (nested_nspace);
8553                         }
8554                         if (match)
8555                                 break;
8556                 }
8557
8558                 if (!klass)
8559                         break;
8560         }
8561         if (!klass)
8562                 return NULL;
8563
8564         if (info->type_arguments) {
8565                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8566                 MonoReflectionType *the_type;
8567                 MonoType *instance;
8568                 int i;
8569
8570                 for (i = 0; i < info->type_arguments->len; i++) {
8571                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8572
8573                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8574                         if (!type_args [i]) {
8575                                 g_free (type_args);
8576                                 return NULL;
8577                         }
8578                 }
8579
8580                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8581                 if (!the_type)
8582                         return NULL;
8583
8584                 instance = mono_reflection_bind_generic_parameters (
8585                         the_type, info->type_arguments->len, type_args, error);
8586
8587                 g_free (type_args);
8588                 if (!instance)
8589                         return NULL;
8590
8591                 klass = mono_class_from_mono_type (instance);
8592         }
8593
8594         for (mod = info->modifiers; mod; mod = mod->next) {
8595                 modval = GPOINTER_TO_UINT (mod->data);
8596                 if (!modval) { /* byref: must be last modifier */
8597                         return &klass->this_arg;
8598                 } else if (modval == -1) {
8599                         klass = mono_ptr_class_get (&klass->byval_arg);
8600                 } else if (modval == -2) {
8601                         bounded = TRUE;
8602                 } else { /* array rank */
8603                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8604                 }
8605         }
8606
8607         return &klass->byval_arg;
8608 }
8609
8610 /*
8611  * mono_reflection_get_type:
8612  * @image: a metadata context
8613  * @info: type description structure
8614  * @ignorecase: flag for case-insensitive string compares
8615  * @type_resolve: whenever type resolve was already tried
8616  *
8617  * Build a MonoType from the type description in @info.
8618  * 
8619  */
8620
8621 MonoType*
8622 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8623         MonoError error;
8624         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8625         mono_error_cleanup (&error);
8626         return result;
8627 }
8628
8629 /**
8630  * mono_reflection_get_type_checked:
8631  * @image: a metadata context
8632  * @info: type description structure
8633  * @ignorecase: flag for case-insensitive string compares
8634  * @type_resolve: whenever type resolve was already tried
8635  * @error: set on error.
8636  *
8637  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8638  *
8639  */
8640 MonoType*
8641 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8642         mono_error_init (error);
8643         return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8644 }
8645
8646
8647 static MonoType*
8648 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8649 {
8650         MonoReflectionAssemblyBuilder *abuilder;
8651         MonoType *type;
8652         int i;
8653
8654         mono_error_init (error);
8655         g_assert (assembly_is_dynamic (assembly));
8656         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8657         if (!abuilder)
8658                 return NULL;
8659
8660         /* Enumerate all modules */
8661
8662         type = NULL;
8663         if (abuilder->modules) {
8664                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8665                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8666                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8667                         if (type)
8668                                 break;
8669                         if (!mono_error_ok (error))
8670                                 return NULL;
8671                 }
8672         }
8673
8674         if (!type && abuilder->loaded_modules) {
8675                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8676                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8677                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8678                         if (type)
8679                                 break;
8680                         if (!mono_error_ok (error))
8681                                 return NULL;
8682                 }
8683         }
8684
8685         return type;
8686 }
8687         
8688 MonoType*
8689 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8690 {
8691         MonoType *type;
8692         MonoReflectionAssembly *assembly;
8693         GString *fullName;
8694         GList *mod;
8695
8696         mono_error_init (error);
8697
8698         if (image && image_is_dynamic (image))
8699                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8700         else {
8701                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8702         }
8703         return_val_if_nok (error, NULL);
8704
8705         if (type)
8706                 return type;
8707         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8708                 return NULL;
8709
8710         if (type_resolve) {
8711                 if (*type_resolve) 
8712                         return NULL;
8713                 else
8714                         *type_resolve = TRUE;
8715         }
8716         
8717         /* Reconstruct the type name */
8718         fullName = g_string_new ("");
8719         if (info->name_space && (info->name_space [0] != '\0'))
8720                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8721         else
8722                 g_string_printf (fullName, "%s", info->name);
8723         for (mod = info->nested; mod; mod = mod->next)
8724                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8725
8726         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8727         if (!is_ok (error)) {
8728                 g_string_free (fullName, TRUE);
8729                 return NULL;
8730         }
8731
8732         if (assembly) {
8733                 if (assembly_is_dynamic (assembly->assembly))
8734                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8735                                                                           info, ignorecase, error);
8736                 else
8737                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8738                                                                   info, ignorecase, error);
8739         }
8740         g_string_free (fullName, TRUE);
8741         return_val_if_nok (error, NULL);
8742         return type;
8743 }
8744
8745 void
8746 mono_reflection_free_type_info (MonoTypeNameParse *info)
8747 {
8748         g_list_free (info->modifiers);
8749         g_list_free (info->nested);
8750
8751         if (info->type_arguments) {
8752                 int i;
8753
8754                 for (i = 0; i < info->type_arguments->len; i++) {
8755                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8756
8757                         mono_reflection_free_type_info (subinfo);
8758                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8759                         g_free (subinfo);
8760                 }
8761
8762                 g_ptr_array_free (info->type_arguments, TRUE);
8763         }
8764 }
8765
8766 /*
8767  * mono_reflection_type_from_name:
8768  * @name: type name.
8769  * @image: a metadata context (can be NULL).
8770  *
8771  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8772  * it defaults to get the type from @image or, if @image is NULL or loading
8773  * from it fails, uses corlib.
8774  * 
8775  */
8776 MonoType*
8777 mono_reflection_type_from_name (char *name, MonoImage *image)
8778 {
8779         MonoError error;
8780         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8781         mono_error_cleanup (&error);
8782         return result;
8783 }
8784
8785 /**
8786  * mono_reflection_type_from_name_checked:
8787  * @name: type name.
8788  * @image: a metadata context (can be NULL).
8789  * @error: set on errror.
8790  *
8791  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8792  * it defaults to get the type from @image or, if @image is NULL or loading
8793  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8794  * 
8795  */
8796 MonoType*
8797 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8798 {
8799         MonoType *type = NULL;
8800         MonoTypeNameParse info;
8801         char *tmp;
8802
8803         mono_error_init (error);
8804         /* Make a copy since parse_type modifies its argument */
8805         tmp = g_strdup (name);
8806         
8807         /*g_print ("requested type %s\n", str);*/
8808         if (mono_reflection_parse_type (tmp, &info)) {
8809                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8810                 if (!is_ok (error)) {
8811                         g_free (tmp);
8812                         mono_reflection_free_type_info (&info);
8813                         return NULL;
8814                 }
8815         }
8816
8817         g_free (tmp);
8818         mono_reflection_free_type_info (&info);
8819         return type;
8820 }
8821
8822 /*
8823  * mono_reflection_get_token:
8824  *
8825  *   Return the metadata token of OBJ which should be an object
8826  * representing a metadata element.
8827  */
8828 guint32
8829 mono_reflection_get_token (MonoObject *obj)
8830 {
8831         MonoError error;
8832         guint32 result = mono_reflection_get_token_checked (obj, &error);
8833         mono_error_assert_ok (&error);
8834         return result;
8835 }
8836
8837 /**
8838  * mono_reflection_get_token_checked:
8839  * @obj: the object
8840  * @error: set on error
8841  *
8842  *   Return the metadata token of @obj which should be an object
8843  * representing a metadata element.  On failure sets @error.
8844  */
8845 guint32
8846 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8847 {
8848         MonoClass *klass;
8849         guint32 token = 0;
8850
8851         mono_error_init (error);
8852
8853         klass = obj->vtable->klass;
8854
8855         if (strcmp (klass->name, "MethodBuilder") == 0) {
8856                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8857
8858                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8859         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8860                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8861
8862                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8863         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8864                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8865
8866                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8867         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8868                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8869                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8870         } else if (strcmp (klass->name, "MonoType") == 0) {
8871                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8872                 return_val_if_nok (error, 0);
8873                 MonoClass *mc = mono_class_from_mono_type (type);
8874                 if (!mono_class_init (mc)) {
8875                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8876                         return 0;
8877                 }
8878
8879                 token = mc->type_token;
8880         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8881                    strcmp (klass->name, "MonoMethod") == 0 ||
8882                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8883                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8884                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8885                 if (m->method->is_inflated) {
8886                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8887                         return inflated->declaring->token;
8888                 } else {
8889                         token = m->method->token;
8890                 }
8891         } else if (strcmp (klass->name, "MonoField") == 0) {
8892                 MonoReflectionField *f = (MonoReflectionField*)obj;
8893
8894                 if (is_field_on_inst (f->field)) {
8895                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8896
8897                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8898                                 int field_index = f->field - dgclass->fields;
8899                                 MonoObject *obj;
8900
8901                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8902                                 obj = dgclass->field_objects [field_index];
8903                                 return mono_reflection_get_token_checked (obj, error);
8904                         }
8905                 }
8906                 token = mono_class_get_field_token (f->field);
8907         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8908                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8909
8910                 token = mono_class_get_property_token (p->property);
8911         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8912                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8913
8914                 token = mono_class_get_event_token (p->event);
8915         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8916                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8917                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8918                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8919
8920                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8921         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8922                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8923
8924                 token = m->token;
8925         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8926                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8927         } else {
8928                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8929                                                 klass->name_space, klass->name);
8930                 return 0;
8931         }
8932
8933         return token;
8934 }
8935
8936 static MonoClass*
8937 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8938 {
8939         char *n;
8940         MonoType *t;
8941         int slen = mono_metadata_decode_value (p, &p);
8942
8943         mono_error_init (error);
8944
8945         n = (char *)g_memdup (p, slen + 1);
8946         n [slen] = 0;
8947         t = mono_reflection_type_from_name_checked (n, image, error);
8948         if (!t) {
8949                 char *msg = g_strdup (mono_error_get_message (error));
8950                 mono_error_cleanup (error);
8951                 /* We don't free n, it's consumed by mono_error */
8952                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8953                 g_free (msg);
8954                 return NULL;
8955         }
8956         g_free (n);
8957         p += slen;
8958         *end = p;
8959         return mono_class_from_mono_type (t);
8960 }
8961
8962 static void*
8963 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8964 {
8965         int slen, type = t->type;
8966         MonoClass *tklass = t->data.klass;
8967
8968         mono_error_init (error);
8969
8970 handle_enum:
8971         switch (type) {
8972         case MONO_TYPE_U1:
8973         case MONO_TYPE_I1:
8974         case MONO_TYPE_BOOLEAN: {
8975                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8976                 *bval = *p;
8977                 *end = p + 1;
8978                 return bval;
8979         }
8980         case MONO_TYPE_CHAR:
8981         case MONO_TYPE_U2:
8982         case MONO_TYPE_I2: {
8983                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8984                 *val = read16 (p);
8985                 *end = p + 2;
8986                 return val;
8987         }
8988 #if SIZEOF_VOID_P == 4
8989         case MONO_TYPE_U:
8990         case MONO_TYPE_I:
8991 #endif
8992         case MONO_TYPE_R4:
8993         case MONO_TYPE_U4:
8994         case MONO_TYPE_I4: {
8995                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8996                 *val = read32 (p);
8997                 *end = p + 4;
8998                 return val;
8999         }
9000 #if SIZEOF_VOID_P == 8
9001         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9002         case MONO_TYPE_I:
9003 #endif
9004         case MONO_TYPE_U8:
9005         case MONO_TYPE_I8: {
9006                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9007                 *val = read64 (p);
9008                 *end = p + 8;
9009                 return val;
9010         }
9011         case MONO_TYPE_R8: {
9012                 double *val = (double *)g_malloc (sizeof (double));
9013                 readr8 (p, val);
9014                 *end = p + 8;
9015                 return val;
9016         }
9017         case MONO_TYPE_VALUETYPE:
9018                 if (t->data.klass->enumtype) {
9019                         type = mono_class_enum_basetype (t->data.klass)->type;
9020                         goto handle_enum;
9021                 } else {
9022                         MonoClass *k =  t->data.klass;
9023                         
9024                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9025                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9026                                 *val = read64 (p);
9027                                 *end = p + 8;
9028                                 return val;
9029                         }
9030                 }
9031                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9032                 break;
9033                 
9034         case MONO_TYPE_STRING:
9035                 if (*p == (char)0xFF) {
9036                         *end = p + 1;
9037                         return NULL;
9038                 }
9039                 slen = mono_metadata_decode_value (p, &p);
9040                 *end = p + slen;
9041                 return mono_string_new_len (mono_domain_get (), p, slen);
9042         case MONO_TYPE_CLASS: {
9043                 MonoReflectionType *rt;
9044                 char *n;
9045                 MonoType *t;
9046                 if (*p == (char)0xFF) {
9047                         *end = p + 1;
9048                         return NULL;
9049                 }
9050 handle_type:
9051                 slen = mono_metadata_decode_value (p, &p);
9052                 n = (char *)g_memdup (p, slen + 1);
9053                 n [slen] = 0;
9054                 t = mono_reflection_type_from_name_checked (n, image, error);
9055                 if (!t) {
9056                         char *msg = g_strdup (mono_error_get_message (error));
9057                         mono_error_cleanup (error);
9058                         /* We don't free n, it's consumed by mono_error */
9059                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9060                         g_free (msg);
9061                         return NULL;
9062                 }
9063                 g_free (n);
9064                 *end = p + slen;
9065
9066                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9067                 if (!mono_error_ok (error))
9068                         return NULL;
9069
9070                 return rt;
9071         }
9072         case MONO_TYPE_OBJECT: {
9073                 char subt = *p++;
9074                 MonoObject *obj;
9075                 MonoClass *subc = NULL;
9076                 void *val;
9077
9078                 if (subt == 0x50) {
9079                         goto handle_type;
9080                 } else if (subt == 0x0E) {
9081                         type = MONO_TYPE_STRING;
9082                         goto handle_enum;
9083                 } else if (subt == 0x1D) {
9084                         MonoType simple_type = {{0}};
9085                         int etype = *p;
9086                         p ++;
9087
9088                         type = MONO_TYPE_SZARRAY;
9089                         if (etype == 0x50) {
9090                                 tklass = mono_defaults.systemtype_class;
9091                         } else if (etype == 0x55) {
9092                                 tklass = load_cattr_enum_type (image, p, &p, error);
9093                                 if (!mono_error_ok (error))
9094                                         return NULL;
9095                         } else {
9096                                 if (etype == 0x51)
9097                                         /* See Partition II, Appendix B3 */
9098                                         etype = MONO_TYPE_OBJECT;
9099                                 simple_type.type = (MonoTypeEnum)etype;
9100                                 tklass = mono_class_from_mono_type (&simple_type);
9101                         }
9102                         goto handle_enum;
9103                 } else if (subt == 0x55) {
9104                         char *n;
9105                         MonoType *t;
9106                         slen = mono_metadata_decode_value (p, &p);
9107                         n = (char *)g_memdup (p, slen + 1);
9108                         n [slen] = 0;
9109                         t = mono_reflection_type_from_name_checked (n, image, error);
9110                         if (!t) {
9111                                 char *msg = g_strdup (mono_error_get_message (error));
9112                                 mono_error_cleanup (error);
9113                                 /* We don't free n, it's consumed by mono_error */
9114                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9115                                 g_free (msg);
9116                                 return NULL;
9117                         }
9118                         g_free (n);
9119                         p += slen;
9120                         subc = mono_class_from_mono_type (t);
9121                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9122                         MonoType simple_type = {{0}};
9123                         simple_type.type = (MonoTypeEnum)subt;
9124                         subc = mono_class_from_mono_type (&simple_type);
9125                 } else {
9126                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9127                 }
9128                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9129                 obj = NULL;
9130                 if (mono_error_ok (error)) {
9131                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9132                         g_assert (!subc->has_references);
9133                         if (mono_error_ok (error))
9134                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9135                 }
9136
9137                 g_free (val);
9138                 return obj;
9139         }
9140         case MONO_TYPE_SZARRAY: {
9141                 MonoArray *arr;
9142                 guint32 i, alen, basetype;
9143                 alen = read32 (p);
9144                 p += 4;
9145                 if (alen == 0xffffffff) {
9146                         *end = p;
9147                         return NULL;
9148                 }
9149                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9150                 basetype = tklass->byval_arg.type;
9151                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9152                         basetype = mono_class_enum_basetype (tklass)->type;
9153                 switch (basetype)
9154                 {
9155                         case MONO_TYPE_U1:
9156                         case MONO_TYPE_I1:
9157                         case MONO_TYPE_BOOLEAN:
9158                                 for (i = 0; i < alen; i++) {
9159                                         MonoBoolean val = *p++;
9160                                         mono_array_set (arr, MonoBoolean, i, val);
9161                                 }
9162                                 break;
9163                         case MONO_TYPE_CHAR:
9164                         case MONO_TYPE_U2:
9165                         case MONO_TYPE_I2:
9166                                 for (i = 0; i < alen; i++) {
9167                                         guint16 val = read16 (p);
9168                                         mono_array_set (arr, guint16, i, val);
9169                                         p += 2;
9170                                 }
9171                                 break;
9172                         case MONO_TYPE_R4:
9173                         case MONO_TYPE_U4:
9174                         case MONO_TYPE_I4:
9175                                 for (i = 0; i < alen; i++) {
9176                                         guint32 val = read32 (p);
9177                                         mono_array_set (arr, guint32, i, val);
9178                                         p += 4;
9179                                 }
9180                                 break;
9181                         case MONO_TYPE_R8:
9182                                 for (i = 0; i < alen; i++) {
9183                                         double val;
9184                                         readr8 (p, &val);
9185                                         mono_array_set (arr, double, i, val);
9186                                         p += 8;
9187                                 }
9188                                 break;
9189                         case MONO_TYPE_U8:
9190                         case MONO_TYPE_I8:
9191                                 for (i = 0; i < alen; i++) {
9192                                         guint64 val = read64 (p);
9193                                         mono_array_set (arr, guint64, i, val);
9194                                         p += 8;
9195                                 }
9196                                 break;
9197                         case MONO_TYPE_CLASS:
9198                         case MONO_TYPE_OBJECT:
9199                         case MONO_TYPE_STRING:
9200                         case MONO_TYPE_SZARRAY:
9201                                 for (i = 0; i < alen; i++) {
9202                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9203                                         if (!mono_error_ok (error))
9204                                                 return NULL;
9205                                         mono_array_setref (arr, i, item);
9206                                 }
9207                                 break;
9208                         default:
9209                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9210                 }
9211                 *end=p;
9212                 return arr;
9213         }
9214         default:
9215                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9216         }
9217         return NULL;
9218 }
9219
9220 static MonoObject*
9221 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9222 {
9223         mono_error_init (error);
9224
9225         gboolean is_ref = type_is_reference (t);
9226
9227         void *val = load_cattr_value (image, t, p, end, error);
9228         if (!is_ok (error)) {
9229                 if (is_ref)
9230                         g_free (val);
9231                 return NULL;
9232         }
9233
9234         if (is_ref)
9235                 return (MonoObject*)val;
9236
9237         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9238         g_free (val);
9239         return boxed;
9240 }
9241
9242 static MonoObject*
9243 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9244 {
9245         static MonoMethod *ctor;
9246         MonoObject *retval;
9247         void *params [2], *unboxed;
9248
9249         mono_error_init (error);
9250
9251         if (!ctor)
9252                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9253         
9254         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9255         return_val_if_nok (error, NULL);
9256
9257         params [1] = val;
9258         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9259         return_val_if_nok (error, NULL);
9260         unboxed = mono_object_unbox (retval);
9261
9262         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9263         return_val_if_nok (error, NULL);
9264
9265         return retval;
9266 }
9267
9268 static MonoObject*
9269 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9270 {
9271         static MonoMethod *ctor;
9272         MonoObject *retval;
9273         void *unboxed, *params [2];
9274
9275         mono_error_init (error);
9276
9277         if (!ctor)
9278                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9279
9280         params [0] = minfo;
9281         params [1] = typedarg;
9282         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9283         return_val_if_nok (error, NULL);
9284
9285         unboxed = mono_object_unbox (retval);
9286
9287         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9288         return_val_if_nok (error, NULL);
9289
9290         return retval;
9291 }
9292
9293 static gboolean
9294 type_is_reference (MonoType *type)
9295 {
9296         switch (type->type) {
9297         case MONO_TYPE_BOOLEAN:
9298         case MONO_TYPE_CHAR:
9299         case MONO_TYPE_U:
9300         case MONO_TYPE_I:
9301         case MONO_TYPE_U1:
9302         case MONO_TYPE_I1:
9303         case MONO_TYPE_U2:
9304         case MONO_TYPE_I2:
9305         case MONO_TYPE_U4:
9306         case MONO_TYPE_I4:
9307         case MONO_TYPE_U8:
9308         case MONO_TYPE_I8:
9309         case MONO_TYPE_R8:
9310         case MONO_TYPE_R4:
9311         case MONO_TYPE_VALUETYPE:
9312                 return FALSE;
9313         default:
9314                 return TRUE;
9315         }
9316 }
9317
9318 static void
9319 free_param_data (MonoMethodSignature *sig, void **params) {
9320         int i;
9321         for (i = 0; i < sig->param_count; ++i) {
9322                 if (!type_is_reference (sig->params [i]))
9323                         g_free (params [i]);
9324         }
9325 }
9326
9327 /*
9328  * Find the field index in the metadata FieldDef table.
9329  */
9330 static guint32
9331 find_field_index (MonoClass *klass, MonoClassField *field) {
9332         int i;
9333
9334         for (i = 0; i < klass->field.count; ++i) {
9335                 if (field == &klass->fields [i])
9336                         return klass->field.first + 1 + i;
9337         }
9338         return 0;
9339 }
9340
9341 /*
9342  * Find the property index in the metadata Property table.
9343  */
9344 static guint32
9345 find_property_index (MonoClass *klass, MonoProperty *property) {
9346         int i;
9347
9348         for (i = 0; i < klass->ext->property.count; ++i) {
9349                 if (property == &klass->ext->properties [i])
9350                         return klass->ext->property.first + 1 + i;
9351         }
9352         return 0;
9353 }
9354
9355 /*
9356  * Find the event index in the metadata Event table.
9357  */
9358 static guint32
9359 find_event_index (MonoClass *klass, MonoEvent *event) {
9360         int i;
9361
9362         for (i = 0; i < klass->ext->event.count; ++i) {
9363                 if (event == &klass->ext->events [i])
9364                         return klass->ext->event.first + 1 + i;
9365         }
9366         return 0;
9367 }
9368
9369 static MonoObject*
9370 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9371 {
9372         const char *p = (const char*)data;
9373         const char *named;
9374         guint32 i, j, num_named;
9375         MonoObject *attr;
9376         void *params_buf [32];
9377         void **params = NULL;
9378         MonoMethodSignature *sig;
9379         MonoObject *exc = NULL;
9380
9381         mono_error_init (error);
9382
9383         mono_class_init (method->klass);
9384
9385         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9386                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9387                 return NULL;
9388         }
9389
9390         if (len == 0) {
9391                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9392                 if (!mono_error_ok (error)) return NULL;
9393
9394                 mono_runtime_invoke_checked (method, attr, NULL, error);
9395                 if (!mono_error_ok (error))
9396                         return NULL;
9397
9398                 return attr;
9399         }
9400
9401         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9402                 return NULL;
9403
9404         /*g_print ("got attr %s\n", method->klass->name);*/
9405
9406         sig = mono_method_signature (method);
9407         if (sig->param_count < 32) {
9408                 params = params_buf;
9409                 memset (params, 0, sizeof (void*) * sig->param_count);
9410         } else {
9411                 /* Allocate using GC so it gets GC tracking */
9412                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9413         }
9414
9415         /* skip prolog */
9416         p += 2;
9417         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9418                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9419                 if (!mono_error_ok (error))
9420                         goto fail;
9421         }
9422
9423         named = p;
9424         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9425         if (!mono_error_ok (error)) goto fail;
9426
9427         mono_runtime_try_invoke (method, attr, params, &exc, error);
9428         if (!mono_error_ok (error))
9429                 goto fail;
9430         if (exc)
9431                 goto fail;
9432
9433         num_named = read16 (named);
9434         named += 2;
9435         for (j = 0; j < num_named; j++) {
9436                 gint name_len;
9437                 char *name, named_type, data_type;
9438                 named_type = *named++;
9439                 data_type = *named++; /* type of data */
9440                 if (data_type == MONO_TYPE_SZARRAY)
9441                         data_type = *named++;
9442                 if (data_type == MONO_TYPE_ENUM) {
9443                         gint type_len;
9444                         char *type_name;
9445                         type_len = mono_metadata_decode_blob_size (named, &named);
9446                         type_name = (char *)g_malloc (type_len + 1);
9447                         memcpy (type_name, named, type_len);
9448                         type_name [type_len] = 0;
9449                         named += type_len;
9450                         /* FIXME: lookup the type and check type consistency */
9451                         g_free (type_name);
9452                 }
9453                 name_len = mono_metadata_decode_blob_size (named, &named);
9454                 name = (char *)g_malloc (name_len + 1);
9455                 memcpy (name, named, name_len);
9456                 name [name_len] = 0;
9457                 named += name_len;
9458                 if (named_type == 0x53) {
9459                         MonoClassField *field;
9460                         void *val;
9461
9462                         /* how this fail is a blackbox */
9463                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9464                         if (!field) {
9465                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9466                                 g_free (name);
9467                                 goto fail;
9468                         }
9469
9470                         val = load_cattr_value (image, field->type, named, &named, error);
9471                         if (!mono_error_ok (error)) {
9472                                 g_free (name);
9473                                 if (!type_is_reference (field->type))
9474                                         g_free (val);
9475                                 goto fail;
9476                         }
9477
9478                         mono_field_set_value (attr, field, val);
9479                         if (!type_is_reference (field->type))
9480                                 g_free (val);
9481                 } else if (named_type == 0x54) {
9482                         MonoProperty *prop;
9483                         void *pparams [1];
9484                         MonoType *prop_type;
9485
9486                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9487
9488                         if (!prop) {
9489                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9490                                 g_free (name);
9491                                 goto fail;
9492                         }
9493
9494                         if (!prop->set) {
9495                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9496                                 g_free (name);
9497                                 goto fail;
9498                         }
9499
9500                         /* can we have more that 1 arg in a custom attr named property? */
9501                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9502                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9503
9504                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9505                         if (!mono_error_ok (error)) {
9506                                 g_free (name);
9507                                 if (!type_is_reference (prop_type))
9508                                         g_free (pparams [0]);
9509                                 goto fail;
9510                         }
9511
9512
9513                         mono_property_set_value (prop, attr, pparams, NULL);
9514                         if (!type_is_reference (prop_type))
9515                                 g_free (pparams [0]);
9516                 }
9517                 g_free (name);
9518         }
9519
9520         free_param_data (method->signature, params);
9521         if (params != params_buf)
9522                 mono_gc_free_fixed (params);
9523
9524         return attr;
9525
9526 fail:
9527         free_param_data (method->signature, params);
9528         if (params != params_buf)
9529                 mono_gc_free_fixed (params);
9530         if (exc)
9531                 mono_raise_exception ((MonoException*)exc);
9532         return NULL;
9533 }
9534         
9535 /*
9536  * mono_reflection_create_custom_attr_data_args:
9537  *
9538  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9539  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9540  * NAMED_ARG_INFO will contain information about the named arguments.
9541  */
9542 void
9543 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)
9544 {
9545         MonoArray *typedargs, *namedargs;
9546         MonoClass *attrklass;
9547         MonoDomain *domain;
9548         const char *p = (const char*)data;
9549         const char *named;
9550         guint32 i, j, num_named;
9551         CattrNamedArg *arginfo = NULL;
9552
9553         *typed_args = NULL;
9554         *named_args = NULL;
9555         *named_arg_info = NULL;
9556
9557         mono_error_init (error);
9558
9559         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9560                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9561                 return;
9562         }
9563
9564         mono_class_init (method->klass);
9565         
9566         domain = mono_domain_get ();
9567
9568         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9569                 return;
9570
9571         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9572         
9573         /* skip prolog */
9574         p += 2;
9575         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9576                 MonoObject *obj;
9577
9578                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9579                 return_if_nok (error);
9580                 mono_array_setref (typedargs, i, obj);
9581         }
9582
9583         named = p;
9584         num_named = read16 (named);
9585         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9586         named += 2;
9587         attrklass = method->klass;
9588
9589         arginfo = g_new0 (CattrNamedArg, num_named);
9590         *named_arg_info = arginfo;
9591
9592         for (j = 0; j < num_named; j++) {
9593                 gint name_len;
9594                 char *name, named_type, data_type;
9595                 named_type = *named++;
9596                 data_type = *named++; /* type of data */
9597                 if (data_type == MONO_TYPE_SZARRAY)
9598                         data_type = *named++;
9599                 if (data_type == MONO_TYPE_ENUM) {
9600                         gint type_len;
9601                         char *type_name;
9602                         type_len = mono_metadata_decode_blob_size (named, &named);
9603                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9604                                 goto fail;
9605
9606                         type_name = (char *)g_malloc (type_len + 1);
9607                         memcpy (type_name, named, type_len);
9608                         type_name [type_len] = 0;
9609                         named += type_len;
9610                         /* FIXME: lookup the type and check type consistency */
9611                         g_free (type_name);
9612                 }
9613                 name_len = mono_metadata_decode_blob_size (named, &named);
9614                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9615                         goto fail;
9616                 name = (char *)g_malloc (name_len + 1);
9617                 memcpy (name, named, name_len);
9618                 name [name_len] = 0;
9619                 named += name_len;
9620                 if (named_type == 0x53) {
9621                         MonoObject *obj;
9622                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9623
9624                         if (!field) {
9625                                 g_free (name);
9626                                 goto fail;
9627                         }
9628
9629                         arginfo [j].type = field->type;
9630                         arginfo [j].field = field;
9631
9632                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9633                         if (!is_ok (error)) {
9634                                 g_free (name);
9635                                 return;
9636                         }
9637                         mono_array_setref (namedargs, j, obj);
9638
9639                 } else if (named_type == 0x54) {
9640                         MonoObject *obj;
9641                         MonoType *prop_type;
9642                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9643
9644                         if (!prop || !prop->set) {
9645                                 g_free (name);
9646                                 goto fail;
9647                         }
9648
9649                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9650                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9651
9652                         arginfo [j].type = prop_type;
9653                         arginfo [j].prop = prop;
9654
9655                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9656                         if (!is_ok (error)) {
9657                                 g_free (name);
9658                                 return;
9659                         }
9660                         mono_array_setref (namedargs, j, obj);
9661                 }
9662                 g_free (name);
9663         }
9664
9665         *typed_args = typedargs;
9666         *named_args = namedargs;
9667         return;
9668 fail:
9669         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9670         g_free (arginfo);
9671         *named_arg_info = NULL;
9672 }
9673
9674 void
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9676 {
9677         MonoDomain *domain;
9678         MonoArray *typedargs, *namedargs;
9679         MonoImage *image;
9680         MonoMethod *method;
9681         CattrNamedArg *arginfo = NULL;
9682         MonoError error;
9683         int i;
9684
9685         mono_error_init (&error);
9686
9687         *ctor_args = NULL;
9688         *named_args = NULL;
9689
9690         if (len == 0)
9691                 return;
9692
9693         image = assembly->assembly->image;
9694         method = ref_method->method;
9695         domain = mono_object_domain (ref_method);
9696
9697         if (!mono_class_init (method->klass))
9698                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9699
9700         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9701         if (!mono_error_ok (&error))
9702                 goto leave;
9703
9704         if (mono_loader_get_last_error ()) {
9705                 mono_error_set_from_loader_error (&error);
9706                 goto leave;
9707         }
9708
9709         if (!typedargs || !namedargs)
9710                 goto leave;
9711
9712         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9713                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9714                 MonoObject *typedarg;
9715
9716                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9717                 if (!is_ok (&error))
9718                         goto leave;
9719                 mono_array_setref (typedargs, i, typedarg);
9720         }
9721
9722         for (i = 0; i < mono_array_length (namedargs); ++i) {
9723                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9724                 MonoObject *typedarg, *namedarg, *minfo;
9725
9726                 if (arginfo [i].prop) {
9727                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9728                         if (!minfo)
9729                                 goto leave;
9730                 } else {
9731                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9732                         if (!mono_error_ok (&error))
9733                                 goto leave;
9734                 }
9735
9736                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9737                 if (!is_ok (&error))
9738                         goto leave;
9739                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9740                 if (!is_ok (&error))
9741                         goto leave;
9742
9743                 mono_array_setref (namedargs, i, namedarg);
9744         }
9745
9746         *ctor_args = typedargs;
9747         *named_args = namedargs;
9748 leave:
9749         g_free (arginfo);
9750         mono_error_raise_exception (&error);
9751
9752 }
9753
9754 static MonoObject*
9755 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9756 {
9757         static MonoMethod *ctor;
9758
9759         MonoDomain *domain;
9760         MonoObject *attr;
9761         void *params [4];
9762
9763         mono_error_init (error);
9764
9765         g_assert (image->assembly);
9766
9767         if (!ctor)
9768                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9769
9770         domain = mono_domain_get ();
9771         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9772         return_val_if_nok (error, NULL);
9773         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9774         return_val_if_nok (error, NULL);
9775         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9776         return_val_if_nok (error, NULL);
9777         params [2] = (gpointer)&cattr->data;
9778         params [3] = &cattr->data_size;
9779
9780         mono_runtime_invoke_checked (ctor, attr, params, error);
9781         return_val_if_nok (error, NULL);
9782         return attr;
9783 }
9784
9785 static MonoArray*
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9787 {
9788         MonoArray *result;
9789         MonoObject *attr;
9790         int i, n;
9791
9792         mono_error_init (error);
9793
9794         n = 0;
9795         for (i = 0; i < cinfo->num_attrs; ++i) {
9796                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9797                         n ++;
9798         }
9799
9800         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9801         n = 0;
9802         for (i = 0; i < cinfo->num_attrs; ++i) {
9803                 if (!cinfo->attrs [i].ctor) {
9804                         /* The cattr type is not finished yet */
9805                         /* We should include the type name but cinfo doesn't contain it */
9806                         mono_error_set_type_load_name (error, NULL, NULL, "");
9807                         return NULL;
9808                 }
9809                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9810                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9811                         if (!mono_error_ok (error))
9812                                 return result;
9813                         mono_array_setref (result, n, attr);
9814                         n ++;
9815                 }
9816         }
9817         return result;
9818 }
9819
9820 MonoArray*
9821 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9822 {
9823         MonoError error;
9824         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9825         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9826
9827         return result;
9828 }
9829
9830 static MonoArray*
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9832 {
9833         MonoArray *result;
9834         MonoObject *attr;
9835         int i;
9836         
9837         mono_error_init (error);
9838         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9839         for (i = 0; i < cinfo->num_attrs; ++i) {
9840                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9841                 return_val_if_nok (error, NULL);
9842                 mono_array_setref (result, i, attr);
9843         }
9844         return result;
9845 }
9846
9847 /**
9848  * mono_custom_attrs_from_index:
9849  *
9850  * Returns: NULL if no attributes are found or if a loading error occurs.
9851  */
9852 MonoCustomAttrInfo*
9853 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9854 {
9855         MonoError error;
9856         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9857         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9858         return result;
9859 }
9860 /**
9861  * mono_custom_attrs_from_index_checked:
9862  *
9863  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9864  */
9865 MonoCustomAttrInfo*
9866 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9867 {
9868         guint32 mtoken, i, len;
9869         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9870         MonoTableInfo *ca;
9871         MonoCustomAttrInfo *ainfo;
9872         GList *tmp, *list = NULL;
9873         const char *data;
9874         MonoCustomAttrEntry* attr;
9875
9876         mono_error_init (error);
9877
9878         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9879
9880         i = mono_metadata_custom_attrs_from_index (image, idx);
9881         if (!i)
9882                 return NULL;
9883         i --;
9884         while (i < ca->rows) {
9885                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9886                         break;
9887                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9888                 ++i;
9889         }
9890         len = g_list_length (list);
9891         if (!len)
9892                 return NULL;
9893         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9894         ainfo->num_attrs = len;
9895         ainfo->image = image;
9896         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9897                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9898                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9899                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9900                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9901                         mtoken |= MONO_TOKEN_METHOD_DEF;
9902                         break;
9903                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9904                         mtoken |= MONO_TOKEN_MEMBER_REF;
9905                         break;
9906                 default:
9907                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9908                         break;
9909                 }
9910                 attr = &ainfo->attrs [i - 1];
9911                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9912                 if (!attr->ctor) {
9913                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9914                         g_list_free (list);
9915                         g_free (ainfo);
9916                         return NULL;
9917                 }
9918
9919                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9920                         /*FIXME raising an exception here doesn't make any sense*/
9921                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9922                         g_list_free (list);
9923                         g_free (ainfo);
9924                         return NULL;
9925                 }
9926                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9927                 attr->data_size = mono_metadata_decode_value (data, &data);
9928                 attr->data = (guchar*)data;
9929         }
9930         g_list_free (list);
9931
9932         return ainfo;
9933 }
9934
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_method (MonoMethod *method)
9937 {
9938         MonoError error;
9939         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9940         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941         return result;
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9946 {
9947         guint32 idx;
9948
9949         mono_error_init (error);
9950
9951         /*
9952          * An instantiated method has the same cattrs as the generic method definition.
9953          *
9954          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9956          */
9957         if (method->is_inflated)
9958                 method = ((MonoMethodInflated *) method)->declaring;
9959         
9960         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9961                 return lookup_custom_attr (method->klass->image, method);
9962
9963         if (!method->token)
9964                 /* Synthetic methods */
9965                 return NULL;
9966
9967         idx = mono_method_get_index (method);
9968         idx <<= MONO_CUSTOM_ATTR_BITS;
9969         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9970         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9971 }
9972
9973 MonoCustomAttrInfo*
9974 mono_custom_attrs_from_class (MonoClass *klass)
9975 {
9976         MonoError error;
9977         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9978         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9979         return result;
9980 }
9981
9982 MonoCustomAttrInfo*
9983 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9984 {
9985         guint32 idx;
9986
9987         mono_error_init (error);
9988
9989         if (klass->generic_class)
9990                 klass = klass->generic_class->container_class;
9991
9992         if (image_is_dynamic (klass->image))
9993                 return lookup_custom_attr (klass->image, klass);
9994
9995         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9996                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9997                 idx <<= MONO_CUSTOM_ATTR_BITS;
9998                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9999         } else {
10000                 idx = mono_metadata_token_index (klass->type_token);
10001                 idx <<= MONO_CUSTOM_ATTR_BITS;
10002                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10003         }
10004         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10005 }
10006
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10009 {
10010         MonoError error;
10011         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10012         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10013         return result;
10014 }
10015
10016 MonoCustomAttrInfo*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10018 {
10019         guint32 idx;
10020         
10021         mono_error_init (error);
10022
10023         if (image_is_dynamic (assembly->image))
10024                 return lookup_custom_attr (assembly->image, assembly);
10025         idx = 1; /* there is only one assembly */
10026         idx <<= MONO_CUSTOM_ATTR_BITS;
10027         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10028         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10029 }
10030
10031 static MonoCustomAttrInfo*
10032 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10033 {
10034         guint32 idx;
10035         
10036         if (image_is_dynamic (image))
10037                 return lookup_custom_attr (image, image);
10038         idx = 1; /* there is only one module */
10039         idx <<= MONO_CUSTOM_ATTR_BITS;
10040         idx |= MONO_CUSTOM_ATTR_MODULE;
10041         return mono_custom_attrs_from_index_checked (image, idx, error);
10042 }
10043
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10046 {
10047         MonoError error;
10048         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10049         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10050         return result;
10051 }
10052
10053 MonoCustomAttrInfo*
10054 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10055 {
10056         guint32 idx;
10057         
10058         if (image_is_dynamic (klass->image)) {
10059                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10060                 return lookup_custom_attr (klass->image, property);
10061         }
10062         idx = find_property_index (klass, property);
10063         idx <<= MONO_CUSTOM_ATTR_BITS;
10064         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10065         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10066 }
10067
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10070 {
10071         MonoError error;
10072         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10073         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10074         return result;
10075 }
10076
10077 MonoCustomAttrInfo*
10078 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10079 {
10080         guint32 idx;
10081         
10082         if (image_is_dynamic (klass->image)) {
10083                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10084                 return lookup_custom_attr (klass->image, event);
10085         }
10086         idx = find_event_index (klass, event);
10087         idx <<= MONO_CUSTOM_ATTR_BITS;
10088         idx |= MONO_CUSTOM_ATTR_EVENT;
10089         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10090 }
10091
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10094 {
10095         MonoError error;
10096         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10097         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10098         return result;
10099 }
10100
10101 MonoCustomAttrInfo*
10102 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10103 {
10104         guint32 idx;
10105         mono_error_init (error);
10106
10107         if (image_is_dynamic (klass->image)) {
10108                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10109                 return lookup_custom_attr (klass->image, field);
10110         }
10111         idx = find_field_index (klass, field);
10112         idx <<= MONO_CUSTOM_ATTR_BITS;
10113         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10114         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10115 }
10116
10117 /**
10118  * mono_custom_attrs_from_param:
10119  * @method: handle to the method that we want to retrieve custom parameter information from
10120  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10121  *
10122  * The result must be released with mono_custom_attrs_free().
10123  *
10124  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10125  */
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10128 {
10129         MonoError error;
10130         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10131         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10132         return result;
10133 }
10134
10135 /**
10136  * mono_custom_attrs_from_param_checked:
10137  * @method: handle to the method that we want to retrieve custom parameter information from
10138  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139  * @error: set on error
10140  *
10141  * The result must be released with mono_custom_attrs_free().
10142  *
10143  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10144  */
10145 MonoCustomAttrInfo*
10146 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10147 {
10148         MonoTableInfo *ca;
10149         guint32 i, idx, method_index;
10150         guint32 param_list, param_last, param_pos, found;
10151         MonoImage *image;
10152         MonoReflectionMethodAux *aux;
10153
10154         mono_error_init (error);
10155
10156         /*
10157          * An instantiated method has the same cattrs as the generic method definition.
10158          *
10159          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10161          */
10162         if (method->is_inflated)
10163                 method = ((MonoMethodInflated *) method)->declaring;
10164
10165         if (image_is_dynamic (method->klass->image)) {
10166                 MonoCustomAttrInfo *res, *ainfo;
10167                 int size;
10168
10169                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10170                 if (!aux || !aux->param_cattr)
10171                         return NULL;
10172
10173                 /* Need to copy since it will be freed later */
10174                 ainfo = aux->param_cattr [param];
10175                 if (!ainfo)
10176                         return NULL;
10177                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10178                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10179                 memcpy (res, ainfo, size);
10180                 return res;
10181         }
10182
10183         image = method->klass->image;
10184         method_index = mono_method_get_index (method);
10185         if (!method_index)
10186                 return NULL;
10187         ca = &image->tables [MONO_TABLE_METHOD];
10188
10189         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10190         if (method_index == ca->rows) {
10191                 ca = &image->tables [MONO_TABLE_PARAM];
10192                 param_last = ca->rows + 1;
10193         } else {
10194                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10195                 ca = &image->tables [MONO_TABLE_PARAM];
10196         }
10197         found = FALSE;
10198         for (i = param_list; i < param_last; ++i) {
10199                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10200                 if (param_pos == param) {
10201                         found = TRUE;
10202                         break;
10203                 }
10204         }
10205         if (!found)
10206                 return NULL;
10207         idx = i;
10208         idx <<= MONO_CUSTOM_ATTR_BITS;
10209         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10210         return mono_custom_attrs_from_index_checked (image, idx, error);
10211 }
10212
10213 gboolean
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10215 {
10216         int i;
10217         MonoClass *klass;
10218         for (i = 0; i < ainfo->num_attrs; ++i) {
10219                 klass = ainfo->attrs [i].ctor->klass;
10220                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10221                         return TRUE;
10222         }
10223         return FALSE;
10224 }
10225
10226 MonoObject*
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10228 {
10229         MonoError error;
10230         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10231         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10232         return res;
10233 }
10234
10235 MonoObject*
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10237 {
10238         int i, attr_index;
10239         MonoClass *klass;
10240         MonoArray *attrs;
10241
10242         mono_error_init (error);
10243
10244         attr_index = -1;
10245         for (i = 0; i < ainfo->num_attrs; ++i) {
10246                 klass = ainfo->attrs [i].ctor->klass;
10247                 if (mono_class_has_parent (klass, attr_klass)) {
10248                         attr_index = i;
10249                         break;
10250                 }
10251         }
10252         if (attr_index == -1)
10253                 return NULL;
10254
10255         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10256         if (!mono_error_ok (error))
10257                 return NULL;
10258         return mono_array_get (attrs, MonoObject*, attr_index);
10259 }
10260
10261 /*
10262  * mono_reflection_get_custom_attrs_info:
10263  * @obj: a reflection object handle
10264  *
10265  * Return the custom attribute info for attributes defined for the
10266  * reflection handle @obj. The objects.
10267  *
10268  * FIXME this function leaks like a sieve for SRE objects.
10269  */
10270 MonoCustomAttrInfo*
10271 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10272 {
10273         MonoError error;
10274         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10275         mono_error_assert_ok (&error);
10276         return result;
10277 }
10278
10279 /**
10280  * mono_reflection_get_custom_attrs_info_checked:
10281  * @obj: a reflection object handle
10282  * @error: set on error
10283  *
10284  * Return the custom attribute info for attributes defined for the
10285  * reflection handle @obj. The objects.
10286  *
10287  * On failure returns NULL and sets @error.
10288  *
10289  * FIXME this function leaks like a sieve for SRE objects.
10290  */
10291 MonoCustomAttrInfo*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10293 {
10294         MonoClass *klass;
10295         MonoCustomAttrInfo *cinfo = NULL;
10296         
10297         mono_error_init (error);
10298
10299         klass = obj->vtable->klass;
10300         if (klass == mono_defaults.monotype_class) {
10301                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10302                 return_val_if_nok (error, NULL);
10303                 klass = mono_class_from_mono_type (type);
10304                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10306                 return_val_if_nok (error, NULL);
10307         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10308                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10309                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10310                 return_val_if_nok (error, NULL);
10311         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10312                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10313                 cinfo = mono_custom_attrs_from_module (module->image, error);
10314                 return_val_if_nok (error, NULL);
10315         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10316                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10317                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10318                 return_val_if_nok (error, NULL);
10319         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10320                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10321                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10322                 return_val_if_nok (error, NULL);
10323         } else if (strcmp ("MonoField", klass->name) == 0) {
10324                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10325                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10326                 return_val_if_nok (error, NULL);
10327         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10328                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10329                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10330                 return_val_if_nok (error, NULL);
10331         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10332                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10333                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10334                 return_val_if_nok (error, NULL);
10335         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10336                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10337                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10338                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10339                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10340                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10341                         return_val_if_nok (error, NULL);
10342                 } else if (is_sr_mono_property (member_class)) {
10343                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10344                         MonoMethod *method;
10345                         if (!(method = prop->property->get))
10346                                 method = prop->property->set;
10347                         g_assert (method);
10348
10349                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10350                         return_val_if_nok (error, NULL);
10351                 } 
10352 #ifndef DISABLE_REFLECTION_EMIT
10353                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10354                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10355                         return_val_if_nok (error, NULL);
10356                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10357                         return_val_if_nok (error, NULL);
10358                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10359                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10360                         MonoMethod *method = NULL;
10361                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10362                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10363                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10364                                 method = ((MonoReflectionMethod *)c->cb)->method;
10365                         else
10366                                 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));
10367
10368                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10369                         return_val_if_nok (error, NULL);
10370                 } 
10371 #endif
10372                 else {
10373                         char *type_name = mono_type_get_full_name (member_class);
10374                         mono_error_set_not_supported (error,
10375                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10376                                                       type_name);
10377                         g_free (type_name);
10378                         return NULL;
10379                 }
10380         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10381                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10382                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10383         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10384                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10385                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10386         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10387                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10388                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10389         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10390                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10391                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10392         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10393                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10394                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10395         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10396                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10397                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10398         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10399                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10400                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10401                 return_val_if_nok (error, NULL);
10402         } else { /* handle other types here... */
10403                 g_error ("get custom attrs not yet supported for %s", klass->name);
10404         }
10405
10406         return cinfo;
10407 }
10408
10409 /*
10410  * mono_reflection_get_custom_attrs_by_type:
10411  * @obj: a reflection object handle
10412  *
10413  * Return an array with all the custom attributes defined of the
10414  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10415  * of that type are returned. The objects are fully build. Return NULL if a loading error
10416  * occurs.
10417  */
10418 MonoArray*
10419 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10420 {
10421         MonoArray *result;
10422         MonoCustomAttrInfo *cinfo;
10423
10424         mono_error_init (error);
10425
10426         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10427         return_val_if_nok (error, NULL);
10428         if (cinfo) {
10429                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10430                 if (!result)
10431                         return NULL;
10432                 if (!cinfo->cached)
10433                         mono_custom_attrs_free (cinfo);
10434         } else {
10435                 mono_loader_assert_no_error ();
10436                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10437         }
10438
10439         return result;
10440 }
10441
10442 /*
10443  * mono_reflection_get_custom_attrs:
10444  * @obj: a reflection object handle
10445  *
10446  * Return an array with all the custom attributes defined of the
10447  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10448  * occurs.
10449  */
10450 MonoArray*
10451 mono_reflection_get_custom_attrs (MonoObject *obj)
10452 {
10453         MonoError error;
10454
10455         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10456 }
10457
10458 /*
10459  * mono_reflection_get_custom_attrs_data:
10460  * @obj: a reflection obj handle
10461  *
10462  * Returns an array of System.Reflection.CustomAttributeData,
10463  * which include information about attributes reflected on
10464  * types loaded using the Reflection Only methods
10465  */
10466 MonoArray*
10467 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10468 {
10469         MonoError error;
10470         MonoArray* result;
10471         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10472         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10473         return result;
10474 }
10475
10476 /*
10477  * mono_reflection_get_custom_attrs_data_checked:
10478  * @obj: a reflection obj handle
10479  * @error: set on error
10480  *
10481  * Returns an array of System.Reflection.CustomAttributeData,
10482  * which include information about attributes reflected on
10483  * types loaded using the Reflection Only methods
10484  */
10485 MonoArray*
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10487 {
10488         MonoArray *result;
10489         MonoCustomAttrInfo *cinfo;
10490
10491         mono_error_init (error);
10492
10493         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10494         return_val_if_nok (error, NULL);
10495         if (cinfo) {
10496                 result = mono_custom_attrs_data_construct (cinfo, error);
10497                 return_val_if_nok (error, NULL);
10498                 if (!cinfo->cached)
10499                         mono_custom_attrs_free (cinfo);
10500         } else
10501                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10502
10503         if (mono_loader_get_last_error ())
10504                 mono_error_set_from_loader_error (error);
10505
10506         return result;
10507 }
10508
10509 static MonoReflectionType*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10511 {
10512         static MonoMethod *method_get_underlying_system_type = NULL;
10513         MonoReflectionType *rt;
10514         MonoMethod *usertype_method;
10515
10516         mono_error_init (error);
10517
10518         if (!method_get_underlying_system_type)
10519                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10520
10521         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10522
10523         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10524
10525         return rt;
10526 }
10527
10528
10529 static gboolean
10530 is_corlib_type (MonoClass *klass)
10531 {
10532         return klass->image == mono_defaults.corlib;
10533 }
10534
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536         static MonoClass *cached_class; \
10537         if (cached_class) \
10538                 return cached_class == _class; \
10539         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540                 cached_class = _class; \
10541                 return TRUE; \
10542         } \
10543         return FALSE; \
10544 } while (0) \
10545
10546
10547 #ifndef DISABLE_REFLECTION_EMIT
10548 static gboolean
10549 is_sre_array (MonoClass *klass)
10550 {
10551         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10552 }
10553
10554 static gboolean
10555 is_sre_byref (MonoClass *klass)
10556 {
10557         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10558 }
10559
10560 static gboolean
10561 is_sre_pointer (MonoClass *klass)
10562 {
10563         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10564 }
10565
10566 static gboolean
10567 is_sre_generic_instance (MonoClass *klass)
10568 {
10569         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10570 }
10571
10572 static gboolean
10573 is_sre_type_builder (MonoClass *klass)
10574 {
10575         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10576 }
10577
10578 static gboolean
10579 is_sre_method_builder (MonoClass *klass)
10580 {
10581         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10582 }
10583
10584 static gboolean
10585 is_sre_ctor_builder (MonoClass *klass)
10586 {
10587         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10588 }
10589
10590 static gboolean
10591 is_sre_field_builder (MonoClass *klass)
10592 {
10593         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10594 }
10595
10596 static gboolean
10597 is_sre_method_on_tb_inst (MonoClass *klass)
10598 {
10599         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10600 }
10601
10602 static gboolean
10603 is_sre_ctor_on_tb_inst (MonoClass *klass)
10604 {
10605         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10606 }
10607
10608 MonoType*
10609 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10610 {
10611         MonoClass *klass;
10612         mono_error_init (error);
10613
10614         if (!ref)
10615                 return NULL;
10616         if (ref->type)
10617                 return ref->type;
10618
10619         if (is_usertype (ref)) {
10620                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10621                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10622                         return NULL;
10623                 if (ref->type)
10624                         return ref->type;
10625         }
10626
10627         klass = mono_object_class (ref);
10628
10629         if (is_sre_array (klass)) {
10630                 MonoType *res;
10631                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10632                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10633                 return_val_if_nok (error, NULL);
10634                 g_assert (base);
10635                 if (sre_array->rank == 0) //single dimentional array
10636                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10637                 else
10638                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10639                 sre_array->type.type = res;
10640                 return res;
10641         } else if (is_sre_byref (klass)) {
10642                 MonoType *res;
10643                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10644                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10645                 return_val_if_nok (error, NULL);
10646                 g_assert (base);
10647                 res = &mono_class_from_mono_type (base)->this_arg;
10648                 sre_byref->type.type = res;
10649                 return res;
10650         } else if (is_sre_pointer (klass)) {
10651                 MonoType *res;
10652                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10653                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10654                 return_val_if_nok (error, NULL);
10655                 g_assert (base);
10656                 res = &mono_ptr_class_get (base)->byval_arg;
10657                 sre_pointer->type.type = res;
10658                 return res;
10659         } else if (is_sre_generic_instance (klass)) {
10660                 MonoType *res, **types;
10661                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10662                 int i, count;
10663
10664                 count = mono_array_length (gclass->type_arguments);
10665                 types = g_new0 (MonoType*, count);
10666                 for (i = 0; i < count; ++i) {
10667                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10668                         types [i] = mono_reflection_type_get_handle (t, error);
10669                         if (!types[i] || !is_ok (error)) {
10670                                 g_free (types);
10671                                 return NULL;
10672                         }
10673                 }
10674
10675                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10676                 g_free (types);
10677                 g_assert (res);
10678                 gclass->type.type = res;
10679                 return res;
10680         }
10681
10682         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10683         return NULL;
10684 }
10685
10686 void
10687 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10688 {
10689         MonoError error;
10690         mono_reflection_type_get_handle (type, &error);
10691         mono_error_set_pending_exception (&error);
10692 }
10693
10694 static gboolean
10695 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10696 {
10697         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10698         MonoClass *klass;
10699
10700         mono_error_init (error);
10701
10702         MonoType *res = mono_reflection_type_get_handle (type, error);
10703
10704         if (!res && is_ok (error)) {
10705                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10706         }
10707         return_val_if_nok (error, FALSE);
10708
10709         klass = mono_class_from_mono_type (res);
10710
10711         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712         mono_domain_lock (domain);
10713
10714         if (!image_is_dynamic (klass->image)) {
10715                 mono_class_setup_supertypes (klass);
10716         } else {
10717                 if (!domain->type_hash)
10718                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10719                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10720                 mono_g_hash_table_insert (domain->type_hash, res, type);
10721         }
10722         mono_domain_unlock (domain);
10723         mono_loader_unlock ();
10724
10725         return TRUE;
10726 }
10727
10728 void
10729 mono_reflection_register_with_runtime (MonoReflectionType *type)
10730 {
10731         MonoError error;
10732         (void) reflection_register_with_runtime (type, &error);
10733         mono_error_set_pending_exception (&error);
10734 }
10735
10736 /**
10737  * LOCKING: Assumes the loader lock is held.
10738  */
10739 static MonoMethodSignature*
10740 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10741         MonoMethodSignature *sig;
10742         int count, i;
10743
10744         mono_error_init (error);
10745
10746         count = parameters? mono_array_length (parameters): 0;
10747
10748         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10749         sig->param_count = count;
10750         sig->sentinelpos = -1; /* FIXME */
10751         for (i = 0; i < count; ++i) {
10752                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10753                 if (!is_ok (error)) {
10754                         image_g_free (image, sig);
10755                         return NULL;
10756                 }
10757         }
10758         return sig;
10759 }
10760
10761 /**
10762  * LOCKING: Assumes the loader lock is held.
10763  */
10764 static MonoMethodSignature*
10765 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10766         MonoMethodSignature *sig;
10767
10768         mono_error_init (error);
10769
10770         sig = parameters_to_signature (image, ctor->parameters, error);
10771         return_val_if_nok (error, NULL);
10772         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10773         sig->ret = &mono_defaults.void_class->byval_arg;
10774         return sig;
10775 }
10776
10777 /**
10778  * LOCKING: Assumes the loader lock is held.
10779  */
10780 static MonoMethodSignature*
10781 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10782         MonoMethodSignature *sig;
10783
10784         mono_error_init (error);
10785
10786         sig = parameters_to_signature (image, method->parameters, error);
10787         return_val_if_nok (error, NULL);
10788         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10789         if (method->rtype) {
10790                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10791                 if (!is_ok (error)) {
10792                         image_g_free (image, sig);
10793                         return NULL;
10794                 }
10795         } else {
10796                 sig->ret = &mono_defaults.void_class->byval_arg;
10797         }
10798         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10799         return sig;
10800 }
10801
10802 static MonoMethodSignature*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10804         MonoMethodSignature *sig;
10805
10806         mono_error_init (error);
10807
10808         sig = parameters_to_signature (NULL, method->parameters, error);
10809         return_val_if_nok (error, NULL);
10810         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10811         if (method->rtype) {
10812                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10813                 if (!is_ok (error)) {
10814                         g_free (sig);
10815                         return NULL;
10816                 }
10817         } else {
10818                 sig->ret = &mono_defaults.void_class->byval_arg;
10819         }
10820         sig->generic_param_count = 0;
10821         return sig;
10822 }
10823
10824 static void
10825 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10826 {
10827         mono_error_init (error);
10828         MonoClass *klass = mono_object_class (prop);
10829         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10830                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10831                 *name = mono_string_to_utf8 (pb->name);
10832                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10833         } else {
10834                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10835                 *name = g_strdup (p->property->name);
10836                 if (p->property->get)
10837                         *type = mono_method_signature (p->property->get)->ret;
10838                 else
10839                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10840         }
10841 }
10842
10843 static void
10844 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10845 {
10846         mono_error_init (error);
10847         MonoClass *klass = mono_object_class (field);
10848         if (strcmp (klass->name, "FieldBuilder") == 0) {
10849                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10850                 *name = mono_string_to_utf8 (fb->name);
10851                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10852         } else {
10853                 MonoReflectionField *f = (MonoReflectionField *)field;
10854                 *name = g_strdup (mono_field_get_name (f->field));
10855                 *type = f->field->type;
10856         }
10857 }
10858
10859 #else /* DISABLE_REFLECTION_EMIT */
10860
10861 void
10862 mono_reflection_register_with_runtime (MonoReflectionType *type)
10863 {
10864         /* This is empty */
10865 }
10866
10867 static gboolean
10868 is_sre_type_builder (MonoClass *klass)
10869 {
10870         return FALSE;
10871 }
10872
10873 static gboolean
10874 is_sre_generic_instance (MonoClass *klass)
10875 {
10876         return FALSE;
10877 }
10878
10879 static void
10880 init_type_builder_generics (MonoObject *type)
10881 {
10882 }
10883
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10885
10886
10887 static gboolean
10888 is_sr_mono_field (MonoClass *klass)
10889 {
10890         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10891 }
10892
10893 static gboolean
10894 is_sr_mono_property (MonoClass *klass)
10895 {
10896         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10897 }
10898
10899 static gboolean
10900 is_sr_mono_method (MonoClass *klass)
10901 {
10902         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10903 }
10904
10905 static gboolean
10906 is_sr_mono_cmethod (MonoClass *klass)
10907 {
10908         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10909 }
10910
10911 static gboolean
10912 is_sr_mono_generic_method (MonoClass *klass)
10913 {
10914         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10915 }
10916
10917 static gboolean
10918 is_sr_mono_generic_cmethod (MonoClass *klass)
10919 {
10920         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10921 }
10922
10923 gboolean
10924 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10925 {
10926         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10927 }
10928
10929 static gboolean
10930 is_usertype (MonoReflectionType *ref)
10931 {
10932         MonoClass *klass = mono_object_class (ref);
10933         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10934 }
10935
10936 static MonoReflectionType*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10938 {
10939         mono_error_init (error);
10940         if (!type || type->type)
10941                 return type;
10942
10943         if (is_usertype (type)) {
10944                 type = mono_reflection_type_get_underlying_system_type (type, error);
10945                 return_val_if_nok (error, NULL);
10946                 if (is_usertype (type)) {
10947                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10948                         return NULL;
10949                 }
10950         }
10951
10952         return type;
10953 }
10954 /**
10955  * encode_cattr_value:
10956  * Encode a value in a custom attribute stream of bytes.
10957  * The value to encode is either supplied as an object in argument val
10958  * (valuetypes are boxed), or as a pointer to the data in the
10959  * argument argval.
10960  * @type represents the type of the value
10961  * @buffer is the start of the buffer
10962  * @p the current position in the buffer
10963  * @buflen contains the size of the buffer and is used to return the new buffer size
10964  * if this needs to be realloced.
10965  * @retbuffer and @retp return the start and the position of the buffer
10966  * @error set on error.
10967  */
10968 static void
10969 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10970 {
10971         MonoTypeEnum simple_type;
10972         
10973         mono_error_init (error);
10974         if ((p-buffer) + 10 >= *buflen) {
10975                 char *newbuf;
10976                 *buflen *= 2;
10977                 newbuf = (char *)g_realloc (buffer, *buflen);
10978                 p = newbuf + (p-buffer);
10979                 buffer = newbuf;
10980         }
10981         if (!argval)
10982                 argval = ((char*)arg + sizeof (MonoObject));
10983         simple_type = type->type;
10984 handle_enum:
10985         switch (simple_type) {
10986         case MONO_TYPE_BOOLEAN:
10987         case MONO_TYPE_U1:
10988         case MONO_TYPE_I1:
10989                 *p++ = *argval;
10990                 break;
10991         case MONO_TYPE_CHAR:
10992         case MONO_TYPE_U2:
10993         case MONO_TYPE_I2:
10994                 swap_with_size (p, argval, 2, 1);
10995                 p += 2;
10996                 break;
10997         case MONO_TYPE_U4:
10998         case MONO_TYPE_I4:
10999         case MONO_TYPE_R4:
11000                 swap_with_size (p, argval, 4, 1);
11001                 p += 4;
11002                 break;
11003         case MONO_TYPE_R8:
11004                 swap_with_size (p, argval, 8, 1);
11005                 p += 8;
11006                 break;
11007         case MONO_TYPE_U8:
11008         case MONO_TYPE_I8:
11009                 swap_with_size (p, argval, 8, 1);
11010                 p += 8;
11011                 break;
11012         case MONO_TYPE_VALUETYPE:
11013                 if (type->data.klass->enumtype) {
11014                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11015                         goto handle_enum;
11016                 } else {
11017                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11018                 }
11019                 break;
11020         case MONO_TYPE_STRING: {
11021                 char *str;
11022                 guint32 slen;
11023                 if (!arg) {
11024                         *p++ = 0xFF;
11025                         break;
11026                 }
11027                 str = mono_string_to_utf8 ((MonoString*)arg);
11028                 slen = strlen (str);
11029                 if ((p-buffer) + 10 + slen >= *buflen) {
11030                         char *newbuf;
11031                         *buflen *= 2;
11032                         *buflen += slen;
11033                         newbuf = (char *)g_realloc (buffer, *buflen);
11034                         p = newbuf + (p-buffer);
11035                         buffer = newbuf;
11036                 }
11037                 mono_metadata_encode_value (slen, p, &p);
11038                 memcpy (p, str, slen);
11039                 p += slen;
11040                 g_free (str);
11041                 break;
11042         }
11043         case MONO_TYPE_CLASS: {
11044                 char *str;
11045                 guint32 slen;
11046                 MonoType *arg_type;
11047                 if (!arg) {
11048                         *p++ = 0xFF;
11049                         break;
11050                 }
11051 handle_type:
11052                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11053                 return_if_nok (error);
11054
11055                 str = type_get_qualified_name (arg_type, NULL);
11056                 slen = strlen (str);
11057                 if ((p-buffer) + 10 + slen >= *buflen) {
11058                         char *newbuf;
11059                         *buflen *= 2;
11060                         *buflen += slen;
11061                         newbuf = (char *)g_realloc (buffer, *buflen);
11062                         p = newbuf + (p-buffer);
11063                         buffer = newbuf;
11064                 }
11065                 mono_metadata_encode_value (slen, p, &p);
11066                 memcpy (p, str, slen);
11067                 p += slen;
11068                 g_free (str);
11069                 break;
11070         }
11071         case MONO_TYPE_SZARRAY: {
11072                 int len, i;
11073                 MonoClass *eclass, *arg_eclass;
11074
11075                 if (!arg) {
11076                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11077                         break;
11078                 }
11079                 len = mono_array_length ((MonoArray*)arg);
11080                 *p++ = len & 0xff;
11081                 *p++ = (len >> 8) & 0xff;
11082                 *p++ = (len >> 16) & 0xff;
11083                 *p++ = (len >> 24) & 0xff;
11084                 *retp = p;
11085                 *retbuffer = buffer;
11086                 eclass = type->data.klass;
11087                 arg_eclass = mono_object_class (arg)->element_class;
11088
11089                 if (!eclass) {
11090                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091                         eclass = mono_defaults.object_class;
11092                 }
11093                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11094                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11095                         int elsize = mono_class_array_element_size (arg_eclass);
11096                         for (i = 0; i < len; ++i) {
11097                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11098                                 return_if_nok (error);
11099                                 elptr += elsize;
11100                         }
11101                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11102                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11103                         int elsize = mono_class_array_element_size (eclass);
11104                         for (i = 0; i < len; ++i) {
11105                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11106                                 return_if_nok (error);
11107                                 elptr += elsize;
11108                         }
11109                 } else {
11110                         for (i = 0; i < len; ++i) {
11111                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11112                                 return_if_nok (error);
11113                         }
11114                 }
11115                 break;
11116         }
11117         case MONO_TYPE_OBJECT: {
11118                 MonoClass *klass;
11119                 char *str;
11120                 guint32 slen;
11121
11122                 /*
11123                  * The parameter type is 'object' but the type of the actual
11124                  * argument is not. So we have to add type information to the blob
11125                  * too. This is completely undocumented in the spec.
11126                  */
11127
11128                 if (arg == NULL) {
11129                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11130                         *p++ = 0xFF;
11131                         break;
11132                 }
11133                 
11134                 klass = mono_object_class (arg);
11135
11136                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11137                         *p++ = 0x50;
11138                         goto handle_type;
11139                 } else {
11140                         return_if_nok (error);
11141                 }
11142
11143                 if (klass->enumtype) {
11144                         *p++ = 0x55;
11145                 } else if (klass == mono_defaults.string_class) {
11146                         simple_type = MONO_TYPE_STRING;
11147                         *p++ = 0x0E;
11148                         goto handle_enum;
11149                 } else if (klass->rank == 1) {
11150                         *p++ = 0x1D;
11151                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11152                                 /* See Partition II, Appendix B3 */
11153                                 *p++ = 0x51;
11154                         else
11155                                 *p++ = klass->element_class->byval_arg.type;
11156                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11157                         return_if_nok (error);
11158                         break;
11159                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11160                         *p++ = simple_type = klass->byval_arg.type;
11161                         goto handle_enum;
11162                 } else {
11163                         g_error ("unhandled type in custom attr");
11164                 }
11165                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11166                 slen = strlen (str);
11167                 if ((p-buffer) + 10 + slen >= *buflen) {
11168                         char *newbuf;
11169                         *buflen *= 2;
11170                         *buflen += slen;
11171                         newbuf = (char *)g_realloc (buffer, *buflen);
11172                         p = newbuf + (p-buffer);
11173                         buffer = newbuf;
11174                 }
11175                 mono_metadata_encode_value (slen, p, &p);
11176                 memcpy (p, str, slen);
11177                 p += slen;
11178                 g_free (str);
11179                 simple_type = mono_class_enum_basetype (klass)->type;
11180                 goto handle_enum;
11181         }
11182         default:
11183                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11184         }
11185         *retp = p;
11186         *retbuffer = buffer;
11187 }
11188
11189 static void
11190 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11191 {
11192         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11193                 char *str = type_get_qualified_name (type, NULL);
11194                 int slen = strlen (str);
11195
11196                 *p++ = 0x55;
11197                 /*
11198                  * This seems to be optional...
11199                  * *p++ = 0x80;
11200                  */
11201                 mono_metadata_encode_value (slen, p, &p);
11202                 memcpy (p, str, slen);
11203                 p += slen;
11204                 g_free (str);
11205         } else if (type->type == MONO_TYPE_OBJECT) {
11206                 *p++ = 0x51;
11207         } else if (type->type == MONO_TYPE_CLASS) {
11208                 /* it should be a type: encode_cattr_value () has the check */
11209                 *p++ = 0x50;
11210         } else {
11211                 mono_metadata_encode_value (type->type, p, &p);
11212                 if (type->type == MONO_TYPE_SZARRAY)
11213                         /* See the examples in Partition VI, Annex B */
11214                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11215         }
11216
11217         *retp = p;
11218 }
11219
11220 #ifndef DISABLE_REFLECTION_EMIT
11221 static void
11222 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11223 {
11224         int len;
11225
11226         mono_error_init (error);
11227
11228         /* Preallocate a large enough buffer */
11229         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11230                 char *str = type_get_qualified_name (type, NULL);
11231                 len = strlen (str);
11232                 g_free (str);
11233         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11234                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11235                 len = strlen (str);
11236                 g_free (str);
11237         } else {
11238                 len = 0;
11239         }
11240         len += strlen (name);
11241
11242         if ((p-buffer) + 20 + len >= *buflen) {
11243                 char *newbuf;
11244                 *buflen *= 2;
11245                 *buflen += len;
11246                 newbuf = (char *)g_realloc (buffer, *buflen);
11247                 p = newbuf + (p-buffer);
11248                 buffer = newbuf;
11249         }
11250
11251         encode_field_or_prop_type (type, p, &p);
11252
11253         len = strlen (name);
11254         mono_metadata_encode_value (len, p, &p);
11255         memcpy (p, name, len);
11256         p += len;
11257         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11258         return_if_nok (error);
11259         *retp = p;
11260         *retbuffer = buffer;
11261 }
11262
11263 /**
11264  * mono_reflection_get_custom_attrs_blob:
11265  * @ctor: custom attribute constructor
11266  * @ctorArgs: arguments o the constructor
11267  * @properties:
11268  * @propValues:
11269  * @fields:
11270  * @fieldValues:
11271  * 
11272  * Creates the blob of data that needs to be saved in the metadata and that represents
11273  * the custom attributed described by @ctor, @ctorArgs etc.
11274  * Returns: a Byte array representing the blob of data.
11275  */
11276 MonoArray*
11277 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11278 {
11279         MonoError error;
11280         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11281         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11282         return result;
11283 }
11284
11285 /**
11286  * mono_reflection_get_custom_attrs_blob_checked:
11287  * @ctor: custom attribute constructor
11288  * @ctorArgs: arguments o the constructor
11289  * @properties:
11290  * @propValues:
11291  * @fields:
11292  * @fieldValues:
11293  * @error: set on error
11294  * 
11295  * Creates the blob of data that needs to be saved in the metadata and that represents
11296  * the custom attributed described by @ctor, @ctorArgs etc.
11297  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11298  */
11299 MonoArray*
11300 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11301 {
11302         MonoArray *result = NULL;
11303         MonoMethodSignature *sig;
11304         MonoObject *arg;
11305         char *buffer, *p;
11306         guint32 buflen, i;
11307
11308         mono_error_init (error);
11309
11310         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11311                 /* sig is freed later so allocate it in the heap */
11312                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11313                 if (!is_ok (error)) {
11314                         g_free (sig);
11315                         return NULL;
11316                 }
11317         } else {
11318                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11319         }
11320
11321         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11322         buflen = 256;
11323         p = buffer = (char *)g_malloc (buflen);
11324         /* write the prolog */
11325         *p++ = 1;
11326         *p++ = 0;
11327         for (i = 0; i < sig->param_count; ++i) {
11328                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11329                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11330                 if (!is_ok (error)) goto leave;
11331         }
11332         i = 0;
11333         if (properties)
11334                 i += mono_array_length (properties);
11335         if (fields)
11336                 i += mono_array_length (fields);
11337         *p++ = i & 0xff;
11338         *p++ = (i >> 8) & 0xff;
11339         if (properties) {
11340                 MonoObject *prop;
11341                 for (i = 0; i < mono_array_length (properties); ++i) {
11342                         MonoType *ptype;
11343                         char *pname;
11344
11345                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11346                         get_prop_name_and_type (prop, &pname, &ptype, error);
11347                         if (!is_ok (error)) goto leave;
11348                         *p++ = 0x54; /* PROPERTY signature */
11349                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11350                         g_free (pname);
11351                         if (!is_ok (error)) goto leave;
11352                 }
11353         }
11354
11355         if (fields) {
11356                 MonoObject *field;
11357                 for (i = 0; i < mono_array_length (fields); ++i) {
11358                         MonoType *ftype;
11359                         char *fname;
11360
11361                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11362                         get_field_name_and_type (field, &fname, &ftype, error);
11363                         if (!is_ok (error)) goto leave;
11364                         *p++ = 0x53; /* FIELD signature */
11365                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11366                         g_free (fname);
11367                         if (!is_ok (error)) goto leave;
11368                 }
11369         }
11370
11371         g_assert (p - buffer <= buflen);
11372         buflen = p - buffer;
11373         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11374         p = mono_array_addr (result, char, 0);
11375         memcpy (p, buffer, buflen);
11376 leave:
11377         g_free (buffer);
11378         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11379                 g_free (sig);
11380         return result;
11381 }
11382
11383 /**
11384  * reflection_setup_internal_class:
11385  * @tb: a TypeBuilder object
11386  * @error: set on error
11387  *
11388  * Creates a MonoClass that represents the TypeBuilder.
11389  * This is a trick that lets us simplify a lot of reflection code
11390  * (and will allow us to support Build and Run assemblies easier).
11391  *
11392  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11393  */
11394 static gboolean
11395 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11396 {
11397         MonoClass *klass, *parent;
11398
11399         mono_error_init (error);
11400         RESOLVE_TYPE (tb->parent, error);
11401         return_val_if_nok (error, FALSE);
11402
11403         mono_loader_lock ();
11404
11405         if (tb->parent) {
11406                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11407                 if (!is_ok (error)) {
11408                         mono_loader_unlock ();
11409                         return FALSE;
11410                 }
11411                 /* check so we can compile corlib correctly */
11412                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11413                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11414                         parent = parent_type->data.klass;
11415                 } else {
11416                         parent = mono_class_from_mono_type (parent_type);
11417                 }
11418         } else {
11419                 parent = NULL;
11420         }
11421         
11422         /* the type has already being created: it means we just have to change the parent */
11423         if (tb->type.type) {
11424                 klass = mono_class_from_mono_type (tb->type.type);
11425                 klass->parent = NULL;
11426                 /* fool mono_class_setup_parent */
11427                 klass->supertypes = NULL;
11428                 mono_class_setup_parent (klass, parent);
11429                 mono_class_setup_mono_type (klass);
11430                 mono_loader_unlock ();
11431                 return TRUE;
11432         }
11433
11434         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11435
11436         klass->image = &tb->module->dynamic_image->image;
11437
11438         klass->inited = 1; /* we lie to the runtime */
11439         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11440         if (!is_ok (error))
11441                 goto failure;
11442         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11443         if (!is_ok (error))
11444                 goto failure;
11445         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11446         klass->flags = tb->attrs;
11447         
11448         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11449
11450         klass->element_class = klass;
11451
11452         if (mono_class_get_ref_info (klass) == NULL) {
11453
11454                 mono_class_set_ref_info (klass, tb);
11455
11456                 /* Put into cache so mono_class_get_checked () will find it.
11457                 Skip nested types as those should not be available on the global scope. */
11458                 if (!tb->nesting_type)
11459                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11460
11461                 /*
11462                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11463                 by performing a mono_class_get which does the full resolution.
11464
11465                 Working around this semantics would require us to write a lot of code for no clear advantage.
11466                 */
11467                 mono_image_append_class_to_reflection_info_set (klass);
11468         } else {
11469                 g_assert (mono_class_get_ref_info (klass) == tb);
11470         }
11471
11472         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11473
11474         if (parent != NULL) {
11475                 mono_class_setup_parent (klass, parent);
11476         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11477                 const char *old_n = klass->name;
11478                 /* trick to get relative numbering right when compiling corlib */
11479                 klass->name = "BuildingObject";
11480                 mono_class_setup_parent (klass, mono_defaults.object_class);
11481                 klass->name = old_n;
11482         }
11483
11484         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11485                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11486                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11487                 klass->instance_size = sizeof (MonoObject);
11488                 klass->size_inited = 1;
11489                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11490         }
11491
11492         mono_class_setup_mono_type (klass);
11493
11494         mono_class_setup_supertypes (klass);
11495
11496         /*
11497          * FIXME: handle interfaces.
11498          */
11499
11500         tb->type.type = &klass->byval_arg;
11501
11502         if (tb->nesting_type) {
11503                 g_assert (tb->nesting_type->type);
11504                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11505                 if (!is_ok (error)) goto failure;
11506                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11507         }
11508
11509         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11510
11511         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11512         
11513         mono_loader_unlock ();
11514         return TRUE;
11515
11516 failure:
11517         mono_loader_unlock ();
11518         return FALSE;
11519 }
11520
11521 /**
11522  * mono_reflection_setup_internal_class:
11523  * @tb: a TypeBuilder object
11524  *
11525  * (icall)
11526  * Creates a MonoClass that represents the TypeBuilder.
11527  * This is a trick that lets us simplify a lot of reflection code
11528  * (and will allow us to support Build and Run assemblies easier).
11529  *
11530  */
11531 void
11532 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11533 {
11534         MonoError error;
11535         (void) reflection_setup_internal_class (tb, &error);
11536         mono_error_set_pending_exception (&error);
11537 }
11538
11539 /*
11540  * mono_reflection_setup_generic_class:
11541  * @tb: a TypeBuilder object
11542  *
11543  * Setup the generic class before adding the first generic parameter.
11544  */
11545 void
11546 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11547 {
11548 }
11549
11550 /*
11551  * mono_reflection_create_generic_class:
11552  * @tb: a TypeBuilder object
11553  *
11554  * Creates the generic class after all generic parameters have been added.
11555  */
11556 void
11557 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11558 {
11559         MonoError error;
11560         MonoClass *klass;
11561         int count, i;
11562
11563         klass = mono_class_from_mono_type (tb->type.type);
11564
11565         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11566
11567         if (klass->generic_container || (count == 0))
11568                 return;
11569
11570         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11571
11572         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11573
11574         klass->generic_container->owner.klass = klass;
11575         klass->generic_container->type_argc = count;
11576         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11577
11578         klass->is_generic = 1;
11579
11580         for (i = 0; i < count; i++) {
11581                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11582                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11583                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11584                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11585                 klass->generic_container->type_params [i] = *param;
11586                 /*Make sure we are a diferent type instance */
11587                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11588                 klass->generic_container->type_params [i].info.pklass = NULL;
11589                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11590
11591                 g_assert (klass->generic_container->type_params [i].param.owner);
11592         }
11593
11594         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11595 }
11596
11597 /**
11598  * reflection_create_internal_class:
11599  * @tb: a TypeBuilder object
11600  * @error: set on error
11601  *
11602  * Actually create the MonoClass that is associated with the TypeBuilder.
11603  * On success returns TRUE, on failure returns FALSE and sets @error.
11604  *
11605  */
11606 static gboolean
11607 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11608 {
11609
11610         MonoClass *klass;
11611
11612         mono_error_init (error);
11613         klass = mono_class_from_mono_type (tb->type.type);
11614
11615         mono_loader_lock ();
11616         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11617                 MonoReflectionFieldBuilder *fb;
11618                 MonoClass *ec;
11619                 MonoType *enum_basetype;
11620
11621                 g_assert (tb->fields != NULL);
11622                 g_assert (mono_array_length (tb->fields) >= 1);
11623
11624                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11625
11626                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11627                 if (!is_ok (error)) {
11628                         mono_loader_unlock ();
11629                         return FALSE;
11630                 }
11631                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11632                         mono_loader_unlock ();
11633                         return TRUE;
11634                 }
11635
11636                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11637                 if (!is_ok (error)) {
11638                         mono_loader_unlock ();
11639                         return FALSE;
11640                 }
11641                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11642                 if (!klass->element_class)
11643                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11644
11645                 /*
11646                  * get the element_class from the current corlib.
11647                  */
11648                 ec = default_class_from_mono_type (enum_basetype);
11649                 klass->instance_size = ec->instance_size;
11650                 klass->size_inited = 1;
11651                 /* 
11652                  * this is almost safe to do with enums and it's needed to be able
11653                  * to create objects of the enum type (for use in SetConstant).
11654                  */
11655                 /* FIXME: Does this mean enums can't have method overrides ? */
11656                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11657         }
11658         mono_loader_unlock ();
11659         return TRUE;
11660 }
11661
11662 /**
11663  * mono_reflection_create_internal_class:
11664  * @tb: a TypeBuilder object
11665  *
11666  * (icall)
11667  * Actually create the MonoClass that is associated with the TypeBuilder.
11668  */
11669 void
11670 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11671 {
11672         MonoError error;
11673         (void) reflection_create_internal_class (tb, &error);
11674         mono_error_set_pending_exception (&error);
11675 }
11676
11677 static MonoMarshalSpec*
11678 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11679                                 MonoReflectionMarshal *minfo, MonoError *error)
11680 {
11681         MonoMarshalSpec *res;
11682
11683         mono_error_init (error);
11684
11685         res = image_g_new0 (image, MonoMarshalSpec, 1);
11686         res->native = (MonoMarshalNative)minfo->type;
11687
11688         switch (minfo->type) {
11689         case MONO_NATIVE_LPARRAY:
11690                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11691                 if (minfo->has_size) {
11692                         res->data.array_data.param_num = minfo->param_num;
11693                         res->data.array_data.num_elem = minfo->count;
11694                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11695                 }
11696                 else {
11697                         res->data.array_data.param_num = -1;
11698                         res->data.array_data.num_elem = -1;
11699                         res->data.array_data.elem_mult = -1;
11700                 }
11701                 break;
11702
11703         case MONO_NATIVE_BYVALTSTR:
11704         case MONO_NATIVE_BYVALARRAY:
11705                 res->data.array_data.num_elem = minfo->count;
11706                 break;
11707
11708         case MONO_NATIVE_CUSTOM:
11709                 if (minfo->marshaltyperef) {
11710                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11711                         if (!is_ok (error)) {
11712                                 image_g_free (image, res);
11713                                 return NULL;
11714                         }
11715                         res->data.custom_data.custom_name =
11716                                 type_get_fully_qualified_name (marshaltyperef);
11717                 }
11718                 if (minfo->mcookie)
11719                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11720                 break;
11721
11722         default:
11723                 break;
11724         }
11725
11726         return res;
11727 }
11728 #endif /* !DISABLE_REFLECTION_EMIT */
11729
11730 MonoReflectionMarshalAsAttribute*
11731 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11732                                                         MonoMarshalSpec *spec, MonoError *error)
11733 {
11734         MonoReflectionType *rt;
11735         MonoReflectionMarshalAsAttribute *minfo;
11736         MonoType *mtype;
11737
11738         mono_error_init (error);
11739         
11740         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11741         if (!minfo)
11742                 return NULL;
11743         minfo->utype = spec->native;
11744
11745         switch (minfo->utype) {
11746         case MONO_NATIVE_LPARRAY:
11747                 minfo->array_subtype = spec->data.array_data.elem_type;
11748                 minfo->size_const = spec->data.array_data.num_elem;
11749                 if (spec->data.array_data.param_num != -1)
11750                         minfo->size_param_index = spec->data.array_data.param_num;
11751                 break;
11752
11753         case MONO_NATIVE_BYVALTSTR:
11754         case MONO_NATIVE_BYVALARRAY:
11755                 minfo->size_const = spec->data.array_data.num_elem;
11756                 break;
11757
11758         case MONO_NATIVE_CUSTOM:
11759                 if (spec->data.custom_data.custom_name) {
11760                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11761                         return_val_if_nok  (error, NULL);
11762
11763                         if (mtype) {
11764                                 rt = mono_type_get_object_checked (domain, mtype, error);
11765                                 if (!rt)
11766                                         return NULL;
11767
11768                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11769                         }
11770
11771                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11772                 }
11773                 if (spec->data.custom_data.cookie)
11774                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11775                 break;
11776
11777         default:
11778                 break;
11779         }
11780
11781         return minfo;
11782 }
11783
11784 #ifndef DISABLE_REFLECTION_EMIT
11785 static MonoMethod*
11786 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11787                                          ReflectionMethodBuilder *rmb,
11788                                          MonoMethodSignature *sig)
11789 {
11790         MonoError error;
11791         MonoMethod *m;
11792         MonoMethodWrapper *wrapperm;
11793         MonoMarshalSpec **specs;
11794         MonoReflectionMethodAux *method_aux;
11795         MonoImage *image;
11796         gboolean dynamic;
11797         int i;
11798
11799         mono_error_init (&error);
11800         /*
11801          * Methods created using a MethodBuilder should have their memory allocated
11802          * inside the image mempool, while dynamic methods should have their memory
11803          * malloc'd.
11804          */
11805         dynamic = rmb->refs != NULL;
11806         image = dynamic ? NULL : klass->image;
11807
11808         if (!dynamic)
11809                 g_assert (!klass->generic_class);
11810
11811         mono_loader_lock ();
11812
11813         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11814                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11815                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11816         else
11817                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11818
11819         wrapperm = (MonoMethodWrapper*)m;
11820
11821         m->dynamic = dynamic;
11822         m->slot = -1;
11823         m->flags = rmb->attrs;
11824         m->iflags = rmb->iattrs;
11825         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11826         m->klass = klass;
11827         m->signature = sig;
11828         m->sre_method = TRUE;
11829         m->skip_visibility = rmb->skip_visibility;
11830         if (rmb->table_idx)
11831                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11832
11833         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11834                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11835                         m->string_ctor = 1;
11836
11837                 m->signature->pinvoke = 1;
11838         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11839                 m->signature->pinvoke = 1;
11840
11841                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11842
11843                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11844                 g_assert (mono_error_ok (&error));
11845                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11846                 g_assert (mono_error_ok (&error));
11847                 
11848                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11849
11850                 if (image_is_dynamic (klass->image))
11851                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11852
11853                 mono_loader_unlock ();
11854
11855                 return m;
11856         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11857                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11858                 MonoMethodHeader *header;
11859                 guint32 code_size;
11860                 gint32 max_stack, i;
11861                 gint32 num_locals = 0;
11862                 gint32 num_clauses = 0;
11863                 guint8 *code;
11864
11865                 if (rmb->ilgen) {
11866                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11867                         code_size = rmb->ilgen->code_len;
11868                         max_stack = rmb->ilgen->max_stack;
11869                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11870                         if (rmb->ilgen->ex_handlers)
11871                                 num_clauses = method_count_clauses (rmb->ilgen);
11872                 } else {
11873                         if (rmb->code) {
11874                                 code = mono_array_addr (rmb->code, guint8, 0);
11875                                 code_size = mono_array_length (rmb->code);
11876                                 /* we probably need to run a verifier on the code... */
11877                                 max_stack = 8; 
11878                         }
11879                         else {
11880                                 code = NULL;
11881                                 code_size = 0;
11882                                 max_stack = 8;
11883                         }
11884                 }
11885
11886                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11887                 header->code_size = code_size;
11888                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11889                 memcpy ((char*)header->code, code, code_size);
11890                 header->max_stack = max_stack;
11891                 header->init_locals = rmb->init_locals;
11892                 header->num_locals = num_locals;
11893
11894                 for (i = 0; i < num_locals; ++i) {
11895                         MonoReflectionLocalBuilder *lb = 
11896                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11897
11898                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11899                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11900                         mono_error_assert_ok (&error);
11901                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11902                 }
11903
11904                 header->num_clauses = num_clauses;
11905                 if (num_clauses) {
11906                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11907                                                                  rmb->ilgen, num_clauses, &error);
11908                         mono_error_assert_ok (&error);
11909                 }
11910
11911                 wrapperm->header = header;
11912         }
11913
11914         if (rmb->generic_params) {
11915                 int count = mono_array_length (rmb->generic_params);
11916                 MonoGenericContainer *container = rmb->generic_container;
11917
11918                 g_assert (container);
11919
11920                 container->type_argc = count;
11921                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11922                 container->owner.method = m;
11923                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11924
11925                 m->is_generic = TRUE;
11926                 mono_method_set_generic_container (m, container);
11927
11928                 for (i = 0; i < count; i++) {
11929                         MonoReflectionGenericParam *gp =
11930                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11931                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11932                         mono_error_assert_ok (&error);
11933                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11934                         container->type_params [i] = *param;
11935                 }
11936
11937                 /*
11938                  * The method signature might have pointers to generic parameters that belong to other methods.
11939                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11940                  * generic parameters.
11941                  */
11942                 for (i = 0; i < m->signature->param_count; ++i) {
11943                         MonoType *t = m->signature->params [i];
11944                         if (t->type == MONO_TYPE_MVAR) {
11945                                 MonoGenericParam *gparam =  t->data.generic_param;
11946                                 if (gparam->num < count) {
11947                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11948                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11949                                 }
11950
11951                         }
11952                 }
11953
11954                 if (klass->generic_container) {
11955                         container->parent = klass->generic_container;
11956                         container->context.class_inst = klass->generic_container->context.class_inst;
11957                 }
11958                 container->context.method_inst = mono_get_shared_generic_inst (container);
11959         }
11960
11961         if (rmb->refs) {
11962                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11963                 int i;
11964                 void **data;
11965
11966                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11967
11968                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11969                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11970                 for (i = 0; i < rmb->nrefs; ++i)
11971                         data [i + 1] = rmb->refs [i];
11972         }
11973
11974         method_aux = NULL;
11975
11976         /* Parameter info */
11977         if (rmb->pinfo) {
11978                 if (!method_aux)
11979                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11980                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11981                 for (i = 0; i <= m->signature->param_count; ++i) {
11982                         MonoReflectionParamBuilder *pb;
11983                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11984                                 if ((i > 0) && (pb->attrs)) {
11985                                         /* Make a copy since it might point to a shared type structure */
11986                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11987                                         m->signature->params [i - 1]->attrs = pb->attrs;
11988                                 }
11989
11990                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11991                                         MonoDynamicImage *assembly;
11992                                         guint32 idx, len;
11993                                         MonoTypeEnum def_type;
11994                                         char *p;
11995                                         const char *p2;
11996
11997                                         if (!method_aux->param_defaults) {
11998                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11999                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12000                                         }
12001                                         assembly = (MonoDynamicImage*)klass->image;
12002                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12003                                         /* Copy the data from the blob since it might get realloc-ed */
12004                                         p = assembly->blob.data + idx;
12005                                         len = mono_metadata_decode_blob_size (p, &p2);
12006                                         len += p2 - p;
12007                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12008                                         method_aux->param_default_types [i] = def_type;
12009                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12010                                 }
12011
12012                                 if (pb->name) {
12013                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12014                                         g_assert (mono_error_ok (&error));
12015                                 }
12016                                 if (pb->cattrs) {
12017                                         if (!method_aux->param_cattr)
12018                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12019                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12020                                 }
12021                         }
12022                 }
12023         }
12024
12025         /* Parameter marshalling */
12026         specs = NULL;
12027         if (rmb->pinfo)         
12028                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12029                         MonoReflectionParamBuilder *pb;
12030                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12031                                 if (pb->marshal_info) {
12032                                         if (specs == NULL)
12033                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12034                                         specs [pb->position] = 
12035                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12036                                         if (!is_ok (&error)) {
12037                                                 mono_loader_unlock ();
12038                                                 image_g_free (image, specs);
12039                                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12040                                         }
12041                                 }
12042                         }
12043                 }
12044         if (specs != NULL) {
12045                 if (!method_aux)
12046                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12047                 method_aux->param_marshall = specs;
12048         }
12049
12050         if (image_is_dynamic (klass->image) && method_aux)
12051                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12052
12053         mono_loader_unlock ();
12054
12055         return m;
12056 }       
12057
12058 static MonoMethod*
12059 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12060 {
12061         ReflectionMethodBuilder rmb;
12062         MonoMethodSignature *sig;
12063
12064         mono_loader_lock ();
12065         g_assert (klass->image != NULL);
12066         sig = ctor_builder_to_signature (klass->image, mb, error);
12067         mono_loader_unlock ();
12068         return_val_if_nok (error, NULL);
12069
12070         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12071                 return NULL;
12072
12073         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12074         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12075
12076         /* If we are in a generic class, we might be called multiple times from inflate_method */
12077         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12078                 /* ilgen is no longer needed */
12079                 mb->ilgen = NULL;
12080         }
12081
12082         return mb->mhandle;
12083 }
12084
12085 static MonoMethod*
12086 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12087 {
12088         ReflectionMethodBuilder rmb;
12089         MonoMethodSignature *sig;
12090
12091         mono_error_init (error);
12092
12093         mono_loader_lock ();
12094         g_assert (klass->image != NULL);
12095         sig = method_builder_to_signature (klass->image, mb, error);
12096         mono_loader_unlock ();
12097         return_val_if_nok (error, NULL);
12098
12099         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12100                 return NULL;
12101
12102         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12103         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12104
12105         /* If we are in a generic class, we might be called multiple times from inflate_method */
12106         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12107                 /* ilgen is no longer needed */
12108                 mb->ilgen = NULL;
12109         }
12110         return mb->mhandle;
12111 }
12112
12113 static MonoClassField*
12114 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12115 {
12116         MonoClassField *field;
12117         MonoType *custom;
12118
12119         mono_error_init (error);
12120
12121         field = g_new0 (MonoClassField, 1);
12122
12123         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12124         mono_error_assert_ok (error);
12125         if (fb->attrs || fb->modreq || fb->modopt) {
12126                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12127                 if (!is_ok (error)) {
12128                         g_free (field);
12129                         return NULL;
12130                 }
12131                 field->type = mono_metadata_type_dup (NULL, type);
12132                 field->type->attrs = fb->attrs;
12133
12134                 g_assert (image_is_dynamic (klass->image));
12135                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12136                 g_free (field->type);
12137                 if (!is_ok (error)) {
12138                         g_free (field);
12139                         return NULL;
12140                 }
12141                 field->type = mono_metadata_type_dup (klass->image, custom);
12142                 g_free (custom);
12143         } else {
12144                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12145                 if (!is_ok (error)) {
12146                         g_free (field);
12147                         return NULL;
12148                 }
12149         }
12150         if (fb->offset != -1)
12151                 field->offset = fb->offset;
12152         field->parent = klass;
12153         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12154
12155         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12156
12157         return field;
12158 }
12159 #endif
12160
12161 /**
12162  * mono_reflection_bind_generic_parameters:
12163  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12164  * @type_args: the number of type arguments to bind
12165  * @types: array of type arguments
12166  * @error: set on error
12167  *
12168  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12169  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12170  */
12171 MonoType*
12172 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12173 {
12174         MonoClass *klass;
12175         MonoReflectionTypeBuilder *tb = NULL;
12176         gboolean is_dynamic = FALSE;
12177         MonoClass *geninst;
12178
12179         mono_error_init (error);
12180         
12181         mono_loader_lock ();
12182
12183         if (is_sre_type_builder (mono_object_class (type))) {
12184                 tb = (MonoReflectionTypeBuilder *) type;
12185
12186                 is_dynamic = TRUE;
12187         } else if (is_sre_generic_instance (mono_object_class (type))) {
12188                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12189                 MonoReflectionType *gtd = rgi->generic_type;
12190
12191                 if (is_sre_type_builder (mono_object_class (gtd))) {
12192                         tb = (MonoReflectionTypeBuilder *)gtd;
12193                         is_dynamic = TRUE;
12194                 }
12195         }
12196
12197         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12198         if (tb && tb->generic_container)
12199                 mono_reflection_create_generic_class (tb);
12200
12201         MonoType *t = mono_reflection_type_get_handle (type, error);
12202         if (!is_ok (error)) {
12203                 mono_loader_unlock ();
12204                 return NULL;
12205         }
12206
12207         klass = mono_class_from_mono_type (t);
12208         if (!klass->generic_container) {
12209                 mono_loader_unlock ();
12210                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12211                 return NULL;
12212         }
12213
12214         if (klass->wastypebuilder) {
12215                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12216
12217                 is_dynamic = TRUE;
12218         }
12219
12220         mono_loader_unlock ();
12221
12222         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12223
12224         return &geninst->byval_arg;
12225 }
12226
12227 MonoClass*
12228 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12229 {
12230         MonoGenericClass *gclass;
12231         MonoGenericInst *inst;
12232
12233         g_assert (klass->generic_container);
12234
12235         inst = mono_metadata_get_generic_inst (type_argc, types);
12236         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12237
12238         return mono_generic_class_get_class (gclass);
12239 }
12240
12241 MonoReflectionMethod*
12242 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12243 {
12244         MonoError error;
12245         MonoClass *klass;
12246         MonoMethod *method, *inflated;
12247         MonoMethodInflated *imethod;
12248         MonoGenericContext tmp_context;
12249         MonoGenericInst *ginst;
12250         MonoType **type_argv;
12251         int count, i;
12252
12253         /*FIXME but this no longer should happen*/
12254         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12255 #ifndef DISABLE_REFLECTION_EMIT
12256                 MonoReflectionMethodBuilder *mb = NULL;
12257                 MonoType *tb;
12258                 MonoClass *klass;
12259
12260                 mb = (MonoReflectionMethodBuilder *) rmethod;
12261                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12262                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12263                 klass = mono_class_from_mono_type (tb);
12264
12265                 method = methodbuilder_to_mono_method (klass, mb, &error);
12266                 if (!method)
12267                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12268 #else
12269                 g_assert_not_reached ();
12270                 method = NULL;
12271 #endif
12272         } else {
12273                 method = rmethod->method;
12274         }
12275
12276         klass = method->klass;
12277
12278         if (method->is_inflated)
12279                 method = ((MonoMethodInflated *) method)->declaring;
12280
12281         count = mono_method_signature (method)->generic_param_count;
12282         if (count != mono_array_length (types))
12283                 return NULL;
12284
12285         type_argv = g_new0 (MonoType *, count);
12286         for (i = 0; i < count; i++) {
12287                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12288                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12289                 if (!is_ok (&error)) {
12290                         g_free (type_argv);
12291                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12292                 }
12293         }
12294         ginst = mono_metadata_get_generic_inst (count, type_argv);
12295         g_free (type_argv);
12296
12297         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12298         tmp_context.method_inst = ginst;
12299
12300         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12301         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12302         imethod = (MonoMethodInflated *) inflated;
12303
12304         /*FIXME but I think this is no longer necessary*/
12305         if (image_is_dynamic (method->klass->image)) {
12306                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12307                 /*
12308                  * This table maps metadata structures representing inflated methods/fields
12309                  * to the reflection objects representing their generic definitions.
12310                  */
12311                 mono_image_lock ((MonoImage*)image);
12312                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12313                 mono_image_unlock ((MonoImage*)image);
12314         }
12315
12316         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12317                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12318         
12319         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12320         mono_error_raise_exception (&error); /* FIXME don't raise here */
12321         return ret;
12322 }
12323
12324 #ifndef DISABLE_REFLECTION_EMIT
12325
12326 static MonoMethod *
12327 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12328 {
12329         MonoMethodInflated *imethod;
12330         MonoGenericContext *context;
12331         int i;
12332
12333         /*
12334          * With generic code sharing the klass might not be inflated.
12335          * This can happen because classes inflated with their own
12336          * type arguments are "normalized" to the uninflated class.
12337          */
12338         if (!klass->generic_class)
12339                 return method;
12340
12341         context = mono_class_get_context (klass);
12342
12343         if (klass->method.count && klass->methods) {
12344                 /* Find the already created inflated method */
12345                 for (i = 0; i < klass->method.count; ++i) {
12346                         g_assert (klass->methods [i]->is_inflated);
12347                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12348                                 break;
12349                 }
12350                 g_assert (i < klass->method.count);
12351                 imethod = (MonoMethodInflated*)klass->methods [i];
12352         } else {
12353                 MonoError error;
12354                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12355                 mono_error_assert_ok (&error);
12356         }
12357
12358         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12359                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12360
12361                 mono_image_lock ((MonoImage*)image);
12362                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12363                 mono_image_unlock ((MonoImage*)image);
12364         }
12365         return (MonoMethod *) imethod;
12366 }
12367
12368 static MonoMethod *
12369 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12370 {
12371         MonoMethod *method;
12372         MonoClass *gklass;
12373
12374         mono_error_init (error);
12375
12376         MonoClass *type_class = mono_object_class (type);
12377
12378         if (is_sre_generic_instance (type_class)) {
12379                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12380                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12381                 return_val_if_nok (error, NULL);
12382                 gklass = mono_class_from_mono_type (generic_type);
12383         } else if (is_sre_type_builder (type_class)) {
12384                 MonoType *t = mono_reflection_type_get_handle (type, error);
12385                 return_val_if_nok (error, NULL);
12386                 gklass = mono_class_from_mono_type (t);
12387         } else if (type->type) {
12388                 gklass = mono_class_from_mono_type (type->type);
12389                 gklass = mono_class_get_generic_type_definition (gklass);
12390         } else {
12391                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12392         }
12393
12394         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12395                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12396                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12397                 else {
12398                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12399                         if (!method)
12400                                 return NULL;
12401                 }
12402         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12403                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12404                 if (!method)
12405                         return NULL;
12406         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12407                 method = ((MonoReflectionMethod *) obj)->method;
12408         else {
12409                 method = NULL; /* prevent compiler warning */
12410                 g_error ("can't handle type %s", obj->vtable->klass->name);
12411         }
12412
12413         MonoType *t = mono_reflection_type_get_handle (type, error);
12414         return_val_if_nok (error, NULL);
12415         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12416 }
12417
12418 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12419 static gboolean
12420 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12421 {
12422         MonoGenericClass *gclass;
12423         MonoDynamicGenericClass *dgclass;
12424         MonoClass *klass, *gklass;
12425         MonoType *gtype;
12426         int i;
12427
12428         mono_error_init (error);
12429
12430         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12431         return_val_if_nok (error, FALSE);
12432         klass = mono_class_from_mono_type (gtype);
12433         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12434         gclass = gtype->data.generic_class;
12435
12436         if (!gclass->is_dynamic)
12437                 return TRUE;
12438
12439         dgclass = (MonoDynamicGenericClass *) gclass;
12440
12441         if (dgclass->initialized)
12442                 return TRUE;
12443
12444         gklass = gclass->container_class;
12445         mono_class_init (gklass);
12446
12447         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12448
12449         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12450         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12451         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12452
12453         for (i = 0; i < dgclass->count_fields; i++) {
12454                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12455                 MonoClassField *field, *inflated_field = NULL;
12456
12457                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12458                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12459                         return_val_if_nok (error, FALSE);
12460                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12461                         field = ((MonoReflectionField *) obj)->field;
12462                 else {
12463                         field = NULL; /* prevent compiler warning */
12464                         g_assert_not_reached ();
12465                 }
12466
12467                 dgclass->fields [i] = *field;
12468                 dgclass->fields [i].parent = klass;
12469                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12470                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12471                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12472                 dgclass->field_generic_types [i] = field->type;
12473                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12474                 dgclass->field_objects [i] = obj;
12475
12476                 if (inflated_field) {
12477                         g_free (inflated_field);
12478                 } else {
12479                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12480                 }
12481         }
12482
12483         dgclass->initialized = TRUE;
12484         return TRUE;
12485 }
12486
12487 void
12488 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12489 {
12490         MonoError error;
12491         (void) reflection_generic_class_initialize (type, fields, &error);
12492         mono_error_set_pending_exception (&error);
12493 }
12494
12495 void
12496 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12497 {
12498         MonoDynamicGenericClass *dgclass;
12499         int i;
12500
12501         g_assert (gclass->is_dynamic);
12502
12503         dgclass = (MonoDynamicGenericClass *)gclass;
12504
12505         for (i = 0; i < dgclass->count_fields; ++i) {
12506                 MonoClassField *field = dgclass->fields + i;
12507                 mono_metadata_free_type (field->type);
12508                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12509         }
12510 }
12511
12512 /**
12513  * fix_partial_generic_class:
12514  * @klass: a generic instantiation MonoClass
12515  * @error: set on error
12516  *
12517  * Assumes that the generic container of @klass has its vtable
12518  * initialized, and updates the parent class, insterfaces, methods and
12519  * fields of @klass by inflating the types using the generic context.
12520  *
12521  * On success returns TRUE, on failure returns FALSE and sets @error.
12522  *
12523  */
12524 static gboolean
12525 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12526 {
12527         MonoClass *gklass = klass->generic_class->container_class;
12528         MonoDynamicGenericClass *dgclass;
12529         int i;
12530
12531         mono_error_init (error);
12532
12533         if (klass->wastypebuilder)
12534                 return TRUE;
12535
12536         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12537         if (klass->parent != gklass->parent) {
12538                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12539                 if (mono_error_ok (error)) {
12540                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12541                         mono_metadata_free_type (parent_type);
12542                         if (parent != klass->parent) {
12543                                 /*fool mono_class_setup_parent*/
12544                                 klass->supertypes = NULL;
12545                                 mono_class_setup_parent (klass, parent);
12546                         }
12547                 } else {
12548                         if (gklass->wastypebuilder)
12549                                 klass->wastypebuilder = TRUE;
12550                         return FALSE;
12551                 }
12552         }
12553
12554         if (!dgclass->initialized)
12555                 return TRUE;
12556
12557         if (klass->method.count != gklass->method.count) {
12558                 klass->method.count = gklass->method.count;
12559                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12560
12561                 for (i = 0; i < klass->method.count; i++) {
12562                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12563                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12564                         mono_error_assert_ok (error);
12565                 }
12566         }
12567
12568         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12569                 klass->interface_count = gklass->interface_count;
12570                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12571                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12572
12573                 for (i = 0; i < gklass->interface_count; ++i) {
12574                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12575                         return_val_if_nok (error, FALSE);
12576
12577                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12578                         mono_metadata_free_type (iface_type);
12579
12580                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12581                                 return FALSE;
12582                 }
12583                 klass->interfaces_inited = 1;
12584         }
12585
12586         if (klass->field.count != gklass->field.count) {
12587                 klass->field.count = gklass->field.count;
12588                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12589
12590                 for (i = 0; i < klass->field.count; i++) {
12591                         klass->fields [i] = gklass->fields [i];
12592                         klass->fields [i].parent = klass;
12593                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12594                         return_val_if_nok (error, FALSE);
12595                 }
12596         }
12597
12598         /*We can only finish with this klass once it's parent has as well*/
12599         if (gklass->wastypebuilder)
12600                 klass->wastypebuilder = TRUE;
12601         return TRUE;
12602 }
12603
12604 /**
12605  * ensure_generic_class_runtime_vtable:
12606  * @klass a generic class
12607  * @error set on error
12608  *
12609  * Ensures that the generic container of @klass has a vtable and
12610  * returns TRUE on success.  On error returns FALSE and sets @error.
12611  */
12612 static gboolean
12613 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12614 {
12615         MonoClass *gklass = klass->generic_class->container_class;
12616
12617         mono_error_init (error);
12618
12619         if (!ensure_runtime_vtable (gklass, error))
12620                 return FALSE;
12621
12622         return fix_partial_generic_class (klass, error);
12623 }
12624
12625 /**
12626  * ensure_runtime_vtable:
12627  * @klass the class
12628  * @error set on error
12629  *
12630  * Ensures that @klass has a vtable and returns TRUE on success. On
12631  * error returns FALSE and sets @error.
12632  */
12633 static gboolean
12634 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12635 {
12636         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12637         int i, num, j;
12638
12639         mono_error_init (error);
12640
12641         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12642                 return TRUE;
12643         if (klass->parent)
12644                 if (!ensure_runtime_vtable (klass->parent, error))
12645                         return FALSE;
12646
12647         if (tb) {
12648                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12649                 num += tb->num_methods;
12650                 klass->method.count = num;
12651                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12652                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12653                 for (i = 0; i < num; ++i) {
12654                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12655                         if (!ctor)
12656                                 return FALSE;
12657                         klass->methods [i] = ctor;
12658                 }
12659                 num = tb->num_methods;
12660                 j = i;
12661                 for (i = 0; i < num; ++i) {
12662                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12663                         if (!meth)
12664                                 return FALSE;
12665                         klass->methods [j++] = meth;
12666                 }
12667         
12668                 if (tb->interfaces) {
12669                         klass->interface_count = mono_array_length (tb->interfaces);
12670                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12671                         for (i = 0; i < klass->interface_count; ++i) {
12672                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12673                                 return_val_if_nok (error, FALSE);
12674                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12675                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12676                                         return FALSE;
12677                         }
12678                         klass->interfaces_inited = 1;
12679                 }
12680         } else if (klass->generic_class){
12681                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12682                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12683                         return FALSE;
12684                 }
12685         }
12686
12687         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12688                 int slot_num = 0;
12689                 for (i = 0; i < klass->method.count; ++i) {
12690                         MonoMethod *im = klass->methods [i];
12691                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12692                                 im->slot = slot_num++;
12693                 }
12694                 
12695                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12696                 mono_class_setup_interface_offsets (klass);
12697                 mono_class_setup_interface_id (klass);
12698         }
12699
12700         /*
12701          * The generic vtable is needed even if image->run is not set since some
12702          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12703          * method->slot being defined.
12704          */
12705
12706         /* 
12707          * tb->methods could not be freed since it is used for determining 
12708          * overrides during dynamic vtable construction.
12709          */
12710
12711         return TRUE;
12712 }
12713
12714 static MonoMethod*
12715 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12716 {
12717         mono_error_init (error);
12718         MonoClass *klass = mono_object_class (method);
12719         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12720                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12721                 return sr_method->method;
12722         }
12723         if (is_sre_method_builder (klass)) {
12724                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12725                 return mb->mhandle;
12726         }
12727         if (is_sre_method_on_tb_inst (klass)) {
12728                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12729                 MonoMethod *result;
12730                 /*FIXME move this to a proper method and unify with resolve_object*/
12731                 if (m->method_args) {
12732                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12733                 } else {
12734                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12735                         return_val_if_nok (error, NULL);
12736                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12737                         MonoMethod *mono_method;
12738
12739                         if (is_sre_method_builder (mono_object_class (m->mb)))
12740                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12741                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12742                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12743                         else
12744                                 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)));
12745
12746                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12747                 }
12748                 return result;
12749         }
12750
12751         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12752         return NULL;
12753 }
12754
12755 void
12756 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12757 {
12758         MonoReflectionTypeBuilder *tb;
12759         int i, j, onum;
12760         MonoReflectionMethod *m;
12761
12762         mono_error_init (error);
12763         *overrides = NULL;
12764         *num_overrides = 0;
12765
12766         g_assert (image_is_dynamic (klass->image));
12767
12768         if (!mono_class_get_ref_info (klass))
12769                 return;
12770
12771         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12772
12773         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12774
12775         onum = 0;
12776         if (tb->methods) {
12777                 for (i = 0; i < tb->num_methods; ++i) {
12778                         MonoReflectionMethodBuilder *mb = 
12779                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12780                         if (mb->override_methods)
12781                                 onum += mono_array_length (mb->override_methods);
12782                 }
12783         }
12784
12785         if (onum) {
12786                 *overrides = g_new0 (MonoMethod*, onum * 2);
12787
12788                 onum = 0;
12789                 for (i = 0; i < tb->num_methods; ++i) {
12790                         MonoReflectionMethodBuilder *mb = 
12791                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12792                         if (mb->override_methods) {
12793                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12794                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12795
12796                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12797                                         return_if_nok (error);
12798                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12799
12800                                         g_assert (mb->mhandle);
12801
12802                                         onum ++;
12803                                 }
12804                         }
12805                 }
12806         }
12807
12808         *num_overrides = onum;
12809 }
12810
12811 static void
12812 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12813 {
12814         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12815         MonoReflectionFieldBuilder *fb;
12816         MonoClassField *field;
12817         MonoImage *image = klass->image;
12818         const char *p, *p2;
12819         int i;
12820         guint32 len, idx, real_size = 0;
12821
12822         klass->field.count = tb->num_fields;
12823         klass->field.first = 0;
12824
12825         mono_error_init (error);
12826
12827         if (tb->class_size) {
12828                 if ((tb->packing_size & 0xffffff00) != 0) {
12829                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12830                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12831                         return;
12832                 }
12833                 klass->packing_size = tb->packing_size;
12834                 real_size = klass->instance_size + tb->class_size;
12835         }
12836
12837         if (!klass->field.count) {
12838                 klass->instance_size = MAX (klass->instance_size, real_size);
12839                 return;
12840         }
12841         
12842         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12843         mono_class_alloc_ext (klass);
12844         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12845         /*
12846         This is, guess what, a hack.
12847         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12848         On the static path no field class is resolved, only types are built. This is the right thing to do
12849         but we suck.
12850         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12851         */
12852         klass->size_inited = 1;
12853
12854         for (i = 0; i < klass->field.count; ++i) {
12855                 MonoArray *rva_data;
12856                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12857                 field = &klass->fields [i];
12858                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12859                 if (!mono_error_ok (error))
12860                         return;
12861                 if (fb->attrs) {
12862                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12863                         return_if_nok (error);
12864                         field->type = mono_metadata_type_dup (klass->image, type);
12865                         field->type->attrs = fb->attrs;
12866                 } else {
12867                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12868                         return_if_nok (error);
12869                 }
12870
12871                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12872                         char *base = mono_array_addr (rva_data, char, 0);
12873                         size_t size = mono_array_length (rva_data);
12874                         char *data = (char *)mono_image_alloc (klass->image, size);
12875                         memcpy (data, base, size);
12876                         klass->ext->field_def_values [i].data = data;
12877                 }
12878                 if (fb->offset != -1)
12879                         field->offset = fb->offset;
12880                 field->parent = klass;
12881                 fb->handle = field;
12882                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12883
12884                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12885                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12886                 }
12887                 if (fb->def_value) {
12888                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12889                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12890                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12891                         /* Copy the data from the blob since it might get realloc-ed */
12892                         p = assembly->blob.data + idx;
12893                         len = mono_metadata_decode_blob_size (p, &p2);
12894                         len += p2 - p;
12895                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12896                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12897                 }
12898         }
12899
12900         klass->instance_size = MAX (klass->instance_size, real_size);
12901         mono_class_layout_fields (klass, klass->instance_size);
12902 }
12903
12904 static void
12905 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12906 {
12907         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12908         MonoReflectionPropertyBuilder *pb;
12909         MonoImage *image = klass->image;
12910         MonoProperty *properties;
12911         int i;
12912
12913         mono_error_init (error);
12914
12915         if (!klass->ext)
12916                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12917
12918         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12919         klass->ext->property.first = 0;
12920
12921         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12922         klass->ext->properties = properties;
12923         for (i = 0; i < klass->ext->property.count; ++i) {
12924                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12925                 properties [i].parent = klass;
12926                 properties [i].attrs = pb->attrs;
12927                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12928                 if (!mono_error_ok (error))
12929                         return;
12930                 if (pb->get_method)
12931                         properties [i].get = pb->get_method->mhandle;
12932                 if (pb->set_method)
12933                         properties [i].set = pb->set_method->mhandle;
12934
12935                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12936                 if (pb->def_value) {
12937                         guint32 len, idx;
12938                         const char *p, *p2;
12939                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12940                         if (!klass->ext->prop_def_values)
12941                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12942                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12943                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12944                         /* Copy the data from the blob since it might get realloc-ed */
12945                         p = assembly->blob.data + idx;
12946                         len = mono_metadata_decode_blob_size (p, &p2);
12947                         len += p2 - p;
12948                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12949                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12950                 }
12951         }
12952 }
12953
12954 static MonoReflectionEvent *
12955 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12956 {
12957         mono_error_init (error);
12958
12959         MonoEvent *event = g_new0 (MonoEvent, 1);
12960         MonoClass *klass;
12961
12962         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12963         if (!is_ok (error)) {
12964                 g_free (event);
12965                 return NULL;
12966         }
12967         klass = mono_class_from_mono_type (type);
12968
12969         event->parent = klass;
12970         event->attrs = eb->attrs;
12971         event->name = mono_string_to_utf8 (eb->name);
12972         if (eb->add_method)
12973                 event->add = eb->add_method->mhandle;
12974         if (eb->remove_method)
12975                 event->remove = eb->remove_method->mhandle;
12976         if (eb->raise_method)
12977                 event->raise = eb->raise_method->mhandle;
12978
12979 #ifndef MONO_SMALL_CONFIG
12980         if (eb->other_methods) {
12981                 int j;
12982                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12983                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12984                         MonoReflectionMethodBuilder *mb = 
12985                                 mono_array_get (eb->other_methods,
12986                                                 MonoReflectionMethodBuilder*, j);
12987                         event->other [j] = mb->mhandle;
12988                 }
12989         }
12990 #endif
12991
12992         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12993         if (!is_ok (error)) {
12994 #ifndef MONO_SMALL_CONFIG
12995                 g_free (event->other);
12996 #endif
12997                 g_free (event);
12998                 return NULL;
12999         }
13000         return ev_obj;
13001 }
13002
13003 MonoReflectionEvent *
13004 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13005 {
13006         MonoError error;
13007         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13008         mono_error_set_pending_exception (&error);
13009         return result;
13010 }
13011
13012 static void
13013 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13014 {
13015         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13016         MonoReflectionEventBuilder *eb;
13017         MonoImage *image = klass->image;
13018         MonoEvent *events;
13019         int i;
13020
13021         mono_error_init (error);
13022
13023         if (!klass->ext)
13024                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13025
13026         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13027         klass->ext->event.first = 0;
13028
13029         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13030         klass->ext->events = events;
13031         for (i = 0; i < klass->ext->event.count; ++i) {
13032                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13033                 events [i].parent = klass;
13034                 events [i].attrs = eb->attrs;
13035                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13036                 if (!mono_error_ok (error))
13037                         return;
13038                 if (eb->add_method)
13039                         events [i].add = eb->add_method->mhandle;
13040                 if (eb->remove_method)
13041                         events [i].remove = eb->remove_method->mhandle;
13042                 if (eb->raise_method)
13043                         events [i].raise = eb->raise_method->mhandle;
13044
13045 #ifndef MONO_SMALL_CONFIG
13046                 if (eb->other_methods) {
13047                         int j;
13048                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13049                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13050                                 MonoReflectionMethodBuilder *mb = 
13051                                         mono_array_get (eb->other_methods,
13052                                                                         MonoReflectionMethodBuilder*, j);
13053                                 events [i].other [j] = mb->mhandle;
13054                         }
13055                 }
13056 #endif
13057                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13058         }
13059 }
13060
13061 struct remove_instantiations_user_data
13062 {
13063         MonoClass *klass;
13064         MonoError *error;
13065 };
13066
13067 static gboolean
13068 remove_instantiations_of_and_ensure_contents (gpointer key,
13069                                                   gpointer value,
13070                                                   gpointer user_data)
13071 {
13072         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13073         MonoType *type = (MonoType*)key;
13074         MonoClass *klass = data->klass;
13075         gboolean already_failed = !is_ok (data->error);
13076         MonoError lerror;
13077         MonoError *error = already_failed ? &lerror : data->error;
13078
13079         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13080                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13081                 //Ensure it's safe to use it.
13082                 if (!fix_partial_generic_class (inst_klass, error)) {
13083                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13084                         // Marked the class with failure, but since some other instantiation already failed,
13085                         // just report that one, and swallow the error from this one.
13086                         if (already_failed)
13087                                 mono_error_cleanup (error);
13088                 }
13089                 return TRUE;
13090         } else
13091                 return FALSE;
13092 }
13093
13094 static void
13095 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13096 {
13097         mono_error_init (error);
13098         int i;
13099
13100         if (!arr)
13101                 return;
13102
13103         for (i = 0; i < mono_array_length (arr); ++i) {
13104                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13105                 if (!mono_error_ok (error))
13106                         break;
13107         }
13108 }
13109
13110 MonoReflectionType*
13111 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13112 {
13113         MonoError error;
13114         MonoClass *klass;
13115         MonoDomain* domain;
13116         MonoReflectionType* res;
13117         int i, j;
13118
13119         mono_error_init (&error);
13120
13121         domain = mono_object_domain (tb);
13122         klass = mono_class_from_mono_type (tb->type.type);
13123
13124         /*
13125          * Check for user defined Type subclasses.
13126          */
13127         RESOLVE_TYPE (tb->parent, &error);
13128         if (!is_ok (&error))
13129                 goto failure_unlocked;
13130         check_array_for_usertypes (tb->interfaces, &error);
13131         if (!is_ok (&error))
13132                 goto failure_unlocked;
13133         if (tb->fields) {
13134                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13135                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13136                         if (fb) {
13137                                 RESOLVE_TYPE (fb->type, &error);
13138                                 if (!is_ok (&error))
13139                                         goto failure_unlocked;
13140                                 check_array_for_usertypes (fb->modreq, &error);
13141                                 if (!is_ok (&error))
13142                                         goto failure_unlocked;
13143                                 check_array_for_usertypes (fb->modopt, &error);
13144                                 if (!is_ok (&error))
13145                                         goto failure_unlocked;
13146                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13147                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13148                                         if (!is_ok (&error))
13149                                                 goto failure_unlocked;
13150                                 }
13151                         }
13152                 }
13153         }
13154         if (tb->methods) {
13155                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13156                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13157                         if (mb) {
13158                                 RESOLVE_TYPE (mb->rtype, &error);
13159                                 if (!is_ok (&error))
13160                                         goto failure_unlocked;
13161                                 check_array_for_usertypes (mb->return_modreq, &error);
13162                                 if (!is_ok (&error))
13163                                         goto failure_unlocked;
13164                                 check_array_for_usertypes (mb->return_modopt, &error);
13165                                 if (!is_ok (&error))
13166                                         goto failure_unlocked;
13167                                 check_array_for_usertypes (mb->parameters, &error);
13168                                 if (!is_ok (&error))
13169                                         goto failure_unlocked;
13170                                 if (mb->param_modreq)
13171                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13172                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13173                                                 if (!is_ok (&error))
13174                                                         goto failure_unlocked;
13175                                         }
13176                                 if (mb->param_modopt)
13177                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13178                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13179                                                 if (!is_ok (&error))
13180                                                         goto failure_unlocked;
13181                                         }
13182                         }
13183                 }
13184         }
13185         if (tb->ctors) {
13186                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13187                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13188                         if (mb) {
13189                                 check_array_for_usertypes (mb->parameters, &error);
13190                                 if (!is_ok (&error))
13191                                         goto failure_unlocked;
13192                                 if (mb->param_modreq)
13193                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13194                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13195                                                 if (!is_ok (&error))
13196                                                         goto failure_unlocked;
13197                                         }
13198                                 if (mb->param_modopt)
13199                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13200                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13201                                                 if (!is_ok (&error))
13202                                                         goto failure_unlocked;
13203                                         }
13204                         }
13205                 }
13206         }
13207
13208         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13209
13210         /* 
13211          * we need to lock the domain because the lock will be taken inside
13212          * So, we need to keep the locking order correct.
13213          */
13214         mono_loader_lock ();
13215         mono_domain_lock (domain);
13216         if (klass->wastypebuilder) {
13217                 mono_domain_unlock (domain);
13218                 mono_loader_unlock ();
13219
13220                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13221                 mono_error_set_pending_exception (&error);
13222
13223                 return res;
13224         }
13225         /*
13226          * Fields to set in klass:
13227          * the various flags: delegate/unicode/contextbound etc.
13228          */
13229         klass->flags = tb->attrs;
13230         klass->has_cctor = 1;
13231         klass->has_finalize = 1;
13232         klass->has_finalize_inited = 1;
13233
13234         mono_class_setup_parent (klass, klass->parent);
13235         /* fool mono_class_setup_supertypes */
13236         klass->supertypes = NULL;
13237         mono_class_setup_supertypes (klass);
13238         mono_class_setup_mono_type (klass);
13239
13240 #if 0
13241         if (!((MonoDynamicImage*)klass->image)->run) {
13242                 if (klass->generic_container) {
13243                         /* FIXME: The code below can't handle generic classes */
13244                         klass->wastypebuilder = TRUE;
13245                         mono_loader_unlock ();
13246                         mono_domain_unlock (domain);
13247
13248                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13249                         mono_error_set_pending_exception (&error);
13250
13251                         return res;
13252                 }
13253         }
13254 #endif
13255
13256         /* enums are done right away */
13257         if (!klass->enumtype)
13258                 if (!ensure_runtime_vtable (klass, &error))
13259                         goto failure;
13260
13261         if (tb->subtypes) {
13262                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13263                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13264                         mono_class_alloc_ext (klass);
13265                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13266                         if (!is_ok (&error)) goto failure;
13267                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13268                 }
13269         }
13270
13271         klass->nested_classes_inited = TRUE;
13272
13273         /* fields and object layout */
13274         if (klass->parent) {
13275                 if (!klass->parent->size_inited)
13276                         mono_class_init (klass->parent);
13277                 klass->instance_size = klass->parent->instance_size;
13278                 klass->sizes.class_size = 0;
13279                 klass->min_align = klass->parent->min_align;
13280                 /* if the type has no fields we won't call the field_setup
13281                  * routine which sets up klass->has_references.
13282                  */
13283                 klass->has_references |= klass->parent->has_references;
13284         } else {
13285                 klass->instance_size = sizeof (MonoObject);
13286                 klass->min_align = 1;
13287         }
13288
13289         /* FIXME: handle packing_size and instance_size */
13290         typebuilder_setup_fields (klass, &error);
13291         if (!mono_error_ok (&error))
13292                 goto failure;
13293         typebuilder_setup_properties (klass, &error);
13294         if (!mono_error_ok (&error))
13295                 goto failure;
13296
13297         typebuilder_setup_events (klass, &error);
13298         if (!mono_error_ok (&error))
13299                 goto failure;
13300
13301         klass->wastypebuilder = TRUE;
13302
13303         /* 
13304          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13305          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13306          * we want to return normal System.MonoType objects, so clear these out from the cache.
13307          *
13308          * Together with this we must ensure the contents of all instances to match the created type.
13309          */
13310         if (domain->type_hash && klass->generic_container) {
13311                 struct remove_instantiations_user_data data;
13312                 data.klass = klass;
13313                 data.error = &error;
13314                 mono_error_assert_ok (&error);
13315                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13316                 if (!is_ok (&error))
13317                         goto failure;
13318         }
13319
13320         mono_domain_unlock (domain);
13321         mono_loader_unlock ();
13322
13323         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13324                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13325                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13326                 goto failure_unlocked;
13327         }
13328
13329         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13330         if (!is_ok (&error))
13331                 goto failure_unlocked;
13332
13333         g_assert (res != (MonoReflectionType*)tb);
13334
13335         return res;
13336
13337 failure:
13338         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13339         klass->wastypebuilder = TRUE;
13340         mono_domain_unlock (domain);
13341         mono_loader_unlock ();
13342 failure_unlocked:
13343         mono_error_set_pending_exception (&error);
13344         return NULL;
13345 }
13346
13347 static gboolean
13348 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13349 {
13350         MonoGenericParamFull *param;
13351         MonoImage *image;
13352         MonoClass *pklass;
13353
13354         mono_error_init (error);
13355
13356         image = &gparam->tbuilder->module->dynamic_image->image;
13357
13358         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13359
13360         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13361         mono_error_assert_ok (error);
13362         param->param.num = gparam->index;
13363
13364         if (gparam->mbuilder) {
13365                 if (!gparam->mbuilder->generic_container) {
13366                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13367                         return_val_if_nok (error, FALSE);
13368
13369                         MonoClass *klass = mono_class_from_mono_type (tb);
13370                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13371                         gparam->mbuilder->generic_container->is_method = TRUE;
13372                         /* 
13373                          * Cannot set owner.method, since the MonoMethod is not created yet.
13374                          * Set the image field instead, so type_in_image () works.
13375                          */
13376                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13377                         gparam->mbuilder->generic_container->owner.image = klass->image;
13378                 }
13379                 param->param.owner = gparam->mbuilder->generic_container;
13380         } else if (gparam->tbuilder) {
13381                 if (!gparam->tbuilder->generic_container) {
13382                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13383                         return_val_if_nok (error, FALSE);
13384                         MonoClass *klass = mono_class_from_mono_type (tb);
13385                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13386                         gparam->tbuilder->generic_container->owner.klass = klass;
13387                 }
13388                 param->param.owner = gparam->tbuilder->generic_container;
13389         }
13390
13391         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13392
13393         gparam->type.type = &pklass->byval_arg;
13394
13395         mono_class_set_ref_info (pklass, gparam);
13396         mono_image_append_class_to_reflection_info_set (pklass);
13397
13398         return TRUE;
13399 }
13400
13401 void
13402 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13403 {
13404         MonoError error;
13405         (void) reflection_initialize_generic_parameter (gparam, &error);
13406         mono_error_set_pending_exception (&error);
13407 }
13408
13409
13410 MonoArray *
13411 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13412 {
13413         MonoError error;
13414         MonoReflectionModuleBuilder *module = sig->module;
13415         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13416         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13417         guint32 buflen, i;
13418         MonoArray *result;
13419         SigBuffer buf;
13420
13421         check_array_for_usertypes (sig->arguments, &error);
13422         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13423
13424         sigbuffer_init (&buf, 32);
13425
13426         sigbuffer_add_value (&buf, 0x07);
13427         sigbuffer_add_value (&buf, na);
13428         if (assembly != NULL){
13429                 for (i = 0; i < na; ++i) {
13430                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13431                         encode_reflection_type (assembly, type, &buf, &error);
13432                         if (!is_ok (&error)) goto fail;
13433                 }
13434         }
13435
13436         buflen = buf.p - buf.buf;
13437         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13438         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13439         sigbuffer_free (&buf);
13440         return result;
13441 fail:
13442         sigbuffer_free (&buf);
13443         mono_error_raise_exception (&error); /* FIXME don't raise here */
13444         return NULL;
13445 }
13446
13447 MonoArray *
13448 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13449 {
13450         MonoError error;
13451         MonoDynamicImage *assembly = sig->module->dynamic_image;
13452         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13453         guint32 buflen, i;
13454         MonoArray *result;
13455         SigBuffer buf;
13456
13457         check_array_for_usertypes (sig->arguments, &error);
13458         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13459
13460         sigbuffer_init (&buf, 32);
13461
13462         sigbuffer_add_value (&buf, 0x06);
13463         for (i = 0; i < na; ++i) {
13464                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13465                 encode_reflection_type (assembly, type, &buf, &error);
13466                 if (!is_ok (&error))
13467                         goto fail;
13468         }
13469
13470         buflen = buf.p - buf.buf;
13471         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13472         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13473         sigbuffer_free (&buf);
13474
13475         return result;
13476 fail:
13477         sigbuffer_free (&buf);
13478         mono_error_raise_exception (&error); /* FIXME don't raise here */
13479         return NULL;
13480 }
13481
13482 typedef struct {
13483         MonoMethod *handle;
13484         MonoDomain *domain;
13485 } DynamicMethodReleaseData;
13486
13487 /*
13488  * The runtime automatically clean up those after finalization.
13489 */      
13490 static MonoReferenceQueue *dynamic_method_queue;
13491
13492 static void
13493 free_dynamic_method (void *dynamic_method)
13494 {
13495         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13496         MonoDomain *domain = data->domain;
13497         MonoMethod *method = data->handle;
13498         guint32 dis_link;
13499
13500         mono_domain_lock (domain);
13501         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13502         g_hash_table_remove (domain->method_to_dyn_method, method);
13503         mono_domain_unlock (domain);
13504         g_assert (dis_link);
13505         mono_gchandle_free (dis_link);
13506
13507         mono_runtime_free_method (domain, method);
13508         g_free (data);
13509 }
13510
13511 static gboolean
13512 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13513 {
13514         MonoReferenceQueue *queue;
13515         MonoMethod *handle;
13516         DynamicMethodReleaseData *release_data;
13517         ReflectionMethodBuilder rmb;
13518         MonoMethodSignature *sig;
13519         MonoClass *klass;
13520         MonoDomain *domain;
13521         GSList *l;
13522         int i;
13523
13524         mono_error_init (error);
13525
13526         if (mono_runtime_is_shutting_down ()) {
13527                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13528                 return FALSE;
13529         }
13530
13531         if (!(queue = dynamic_method_queue)) {
13532                 mono_loader_lock ();
13533                 if (!(queue = dynamic_method_queue))
13534                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13535                 mono_loader_unlock ();
13536         }
13537
13538         sig = dynamic_method_to_signature (mb, error);
13539         return_val_if_nok (error, FALSE);
13540
13541         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13542
13543         /*
13544          * Resolve references.
13545          */
13546         /* 
13547          * Every second entry in the refs array is reserved for storing handle_class,
13548          * which is needed by the ldtoken implementation in the JIT.
13549          */
13550         rmb.nrefs = mb->nrefs;
13551         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13552         for (i = 0; i < mb->nrefs; i += 2) {
13553                 MonoClass *handle_class;
13554                 gpointer ref;
13555                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13556
13557                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13558                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13559                         /*
13560                          * The referenced DynamicMethod should already be created by the managed
13561                          * code, except in the case of circular references. In that case, we store
13562                          * method in the refs array, and fix it up later when the referenced 
13563                          * DynamicMethod is created.
13564                          */
13565                         if (method->mhandle) {
13566                                 ref = method->mhandle;
13567                         } else {
13568                                 /* FIXME: GC object stored in unmanaged memory */
13569                                 ref = method;
13570
13571                                 /* FIXME: GC object stored in unmanaged memory */
13572                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13573                         }
13574                         handle_class = mono_defaults.methodhandle_class;
13575                 } else {
13576                         MonoException *ex = NULL;
13577                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13578                         if (!is_ok  (error)) {
13579                                 g_free (rmb.refs);
13580                                 return FALSE;
13581                         }
13582                         if (!ref)
13583                                 ex = mono_get_exception_type_load (NULL, NULL);
13584                         else if (mono_security_core_clr_enabled ())
13585                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13586
13587                         if (ex) {
13588                                 g_free (rmb.refs);
13589                                 mono_error_set_exception_instance (error, ex);
13590                                 return FALSE;
13591                         }
13592                 }
13593
13594                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13595                 rmb.refs [i + 1] = handle_class;
13596         }               
13597
13598         if (mb->owner) {
13599                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13600                 if (!is_ok (error)) {
13601                         g_free (rmb.refs);
13602                         return FALSE;
13603                 }
13604                 klass = mono_class_from_mono_type (owner_type);
13605         } else {
13606                 klass = mono_defaults.object_class;
13607         }
13608
13609         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13610         release_data = g_new (DynamicMethodReleaseData, 1);
13611         release_data->handle = handle;
13612         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13613         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13614                 g_free (release_data);
13615
13616         /* Fix up refs entries pointing at us */
13617         for (l = mb->referenced_by; l; l = l->next) {
13618                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13619                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13620                 gpointer *data;
13621                 
13622                 g_assert (method->mhandle);
13623
13624                 data = (gpointer*)wrapper->method_data;
13625                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13626                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13627                                 data [i + 1] = mb->mhandle;
13628                 }
13629         }
13630         g_slist_free (mb->referenced_by);
13631
13632         g_free (rmb.refs);
13633
13634         /* ilgen is no longer needed */
13635         mb->ilgen = NULL;
13636
13637         domain = mono_domain_get ();
13638         mono_domain_lock (domain);
13639         if (!domain->method_to_dyn_method)
13640                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13641         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13642         mono_domain_unlock (domain);
13643
13644         return TRUE;
13645 }
13646
13647 void
13648 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13649 {
13650         MonoError error;
13651         (void) reflection_create_dynamic_method (mb, &error);
13652         mono_error_set_pending_exception (&error);
13653 }
13654
13655 #endif /* DISABLE_REFLECTION_EMIT */
13656
13657 /**
13658  * 
13659  * mono_reflection_is_valid_dynamic_token:
13660  * 
13661  * Returns TRUE if token is valid.
13662  * 
13663  */
13664 gboolean
13665 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13666 {
13667         return lookup_dyn_token (image, token) != NULL;
13668 }
13669
13670 MonoMethodSignature *
13671 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13672 {
13673         MonoMethodSignature *sig;
13674         g_assert (image_is_dynamic (image));
13675
13676         mono_error_init (error);
13677
13678         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13679         if (sig)
13680                 return sig;
13681
13682         return mono_method_signature_checked (method, error);
13683 }
13684
13685 #ifndef DISABLE_REFLECTION_EMIT
13686
13687 /**
13688  * mono_reflection_lookup_dynamic_token:
13689  *
13690  * Finish the Builder object pointed to by TOKEN and return the corresponding
13691  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13692  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13693  * mapping table.
13694  *
13695  * LOCKING: Take the loader lock
13696  */
13697 gpointer
13698 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13699 {
13700         MonoError error;
13701         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13702         MonoObject *obj;
13703         MonoClass *klass;
13704
13705         obj = lookup_dyn_token (assembly, token);
13706         if (!obj) {
13707                 if (valid_token)
13708                         g_error ("Could not find required dynamic token 0x%08x", token);
13709                 else
13710                         return NULL;
13711         }
13712
13713         if (!handle_class)
13714                 handle_class = &klass;
13715         gpointer result = resolve_object (image, obj, handle_class, context, &error);
13716         mono_error_raise_exception (&error); /* FIXME don't raise here */
13717         return result;
13718 }
13719
13720 /*
13721  * ensure_complete_type:
13722  *
13723  *   Ensure that KLASS is completed if it is a dynamic type, or references
13724  * dynamic types.
13725  */
13726 static void
13727 ensure_complete_type (MonoClass *klass, MonoError *error)
13728 {
13729         mono_error_init (error);
13730
13731         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13732                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13733
13734                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13735                 return_if_nok (error);
13736
13737                 // Asserting here could break a lot of code
13738                 //g_assert (klass->wastypebuilder);
13739         }
13740
13741         if (klass->generic_class) {
13742                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13743                 int i;
13744
13745                 for (i = 0; i < inst->type_argc; ++i) {
13746                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13747                         return_if_nok (error);
13748                 }
13749         }
13750 }
13751
13752 static gpointer
13753 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13754 {
13755         gpointer result = NULL;
13756
13757         mono_error_init (error);
13758
13759         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13760                 result = mono_string_intern_checked ((MonoString*)obj, error);
13761                 return_val_if_nok (error, NULL);
13762                 *handle_class = mono_defaults.string_class;
13763                 g_assert (result);
13764         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13765                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13766                 return_val_if_nok (error, NULL);
13767                 MonoClass *mc = mono_class_from_mono_type (type);
13768                 if (!mono_class_init (mc)) {
13769                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13770                         return NULL;
13771                 }
13772
13773                 if (context) {
13774                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13775                         return_val_if_nok (error, NULL);
13776
13777                         result = mono_class_from_mono_type (inflated);
13778                         mono_metadata_free_type (inflated);
13779                 } else {
13780                         result = mono_class_from_mono_type (type);
13781                 }
13782                 *handle_class = mono_defaults.typehandle_class;
13783                 g_assert (result);
13784         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13785                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13786                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13787                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13788                 result = ((MonoReflectionMethod*)obj)->method;
13789                 if (context) {
13790                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13791                         mono_error_assert_ok (error);
13792                 }
13793                 *handle_class = mono_defaults.methodhandle_class;
13794                 g_assert (result);
13795         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13796                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13797                 result = mb->mhandle;
13798                 if (!result) {
13799                         /* Type is not yet created */
13800                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13801
13802                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13803                         return_val_if_nok (error, NULL);
13804
13805                         /*
13806                          * Hopefully this has been filled in by calling CreateType() on the
13807                          * TypeBuilder.
13808                          */
13809                         /*
13810                          * TODO: This won't work if the application finishes another 
13811                          * TypeBuilder instance instead of this one.
13812                          */
13813                         result = mb->mhandle;
13814                 }
13815                 if (context) {
13816                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13817                         mono_error_assert_ok (error);
13818                 }
13819                 *handle_class = mono_defaults.methodhandle_class;
13820         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13821                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13822
13823                 result = cb->mhandle;
13824                 if (!result) {
13825                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13826
13827                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13828                         return_val_if_nok (error, NULL);
13829                         result = cb->mhandle;
13830                 }
13831                 if (context) {
13832                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13833                         mono_error_assert_ok (error);
13834                 }
13835                 *handle_class = mono_defaults.methodhandle_class;
13836         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13837                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13838
13839                 ensure_complete_type (field->parent, error);
13840                 return_val_if_nok (error, NULL);
13841
13842                 if (context) {
13843                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13844                         return_val_if_nok (error, NULL);
13845
13846                         MonoClass *klass = mono_class_from_mono_type (inflated);
13847                         MonoClassField *inflated_field;
13848                         gpointer iter = NULL;
13849                         mono_metadata_free_type (inflated);
13850                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13851                                 if (!strcmp (field->name, inflated_field->name))
13852                                         break;
13853                         }
13854                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13855                         result = inflated_field;
13856                 } else {
13857                         result = field;
13858                 }
13859                 *handle_class = mono_defaults.fieldhandle_class;
13860                 g_assert (result);
13861         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13862                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13863                 result = fb->handle;
13864
13865                 if (!result) {
13866                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13867
13868                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13869                         return_val_if_nok (error, NULL);
13870                         result = fb->handle;
13871                 }
13872
13873                 if (fb->handle && fb->handle->parent->generic_container) {
13874                         MonoClass *klass = fb->handle->parent;
13875                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13876                         return_val_if_nok (error, NULL);
13877
13878                         MonoClass *inflated = mono_class_from_mono_type (type);
13879
13880                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13881                         g_assert (result);
13882                         mono_metadata_free_type (type);
13883                 }
13884                 *handle_class = mono_defaults.fieldhandle_class;
13885         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13886                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13887                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13888                 return_val_if_nok (error, NULL);
13889                 MonoClass *klass;
13890
13891                 klass = type->data.klass;
13892                 if (klass->wastypebuilder) {
13893                         /* Already created */
13894                         result = klass;
13895                 }
13896                 else {
13897                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13898                         return_val_if_nok (error, NULL);
13899                         result = type->data.klass;
13900                         g_assert (result);
13901                 }
13902                 *handle_class = mono_defaults.typehandle_class;
13903         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13904                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13905                 MonoMethodSignature *sig;
13906                 int nargs, i;
13907
13908                 if (helper->arguments)
13909                         nargs = mono_array_length (helper->arguments);
13910                 else
13911                         nargs = 0;
13912
13913                 sig = mono_metadata_signature_alloc (image, nargs);
13914                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13915                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13916
13917                 if (helper->unmanaged_call_conv) { /* unmanaged */
13918                         sig->call_convention = helper->unmanaged_call_conv - 1;
13919                         sig->pinvoke = TRUE;
13920                 } else if (helper->call_conv & 0x02) {
13921                         sig->call_convention = MONO_CALL_VARARG;
13922                 } else {
13923                         sig->call_convention = MONO_CALL_DEFAULT;
13924                 }
13925
13926                 sig->param_count = nargs;
13927                 /* TODO: Copy type ? */
13928                 sig->ret = helper->return_type->type;
13929                 for (i = 0; i < nargs; ++i) {
13930                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13931                         if (!is_ok (error)) {
13932                                 image_g_free (image, sig);
13933                                 return NULL;
13934                         }
13935                 }
13936
13937                 result = sig;
13938                 *handle_class = NULL;
13939         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13940                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13941                 /* Already created by the managed code */
13942                 g_assert (method->mhandle);
13943                 result = method->mhandle;
13944                 *handle_class = mono_defaults.methodhandle_class;
13945         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13946                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13947                 return_val_if_nok (error, NULL);
13948                 type = mono_class_inflate_generic_type_checked (type, context, error);
13949                 return_val_if_nok (error, NULL);
13950
13951                 result = mono_class_from_mono_type (type);
13952                 *handle_class = mono_defaults.typehandle_class;
13953                 g_assert (result);
13954                 mono_metadata_free_type (type);
13955         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13956                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13957                 return_val_if_nok (error, NULL);
13958                 type = mono_class_inflate_generic_type_checked (type, context, error);
13959                 return_val_if_nok (error, NULL);
13960
13961                 result = mono_class_from_mono_type (type);
13962                 *handle_class = mono_defaults.typehandle_class;
13963                 g_assert (result);
13964                 mono_metadata_free_type (type);
13965         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13966                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13967                 MonoClass *inflated;
13968                 MonoType *type;
13969                 MonoClassField *field;
13970
13971                 if (is_sre_field_builder (mono_object_class (f->fb)))
13972                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13973                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13974                         field = ((MonoReflectionField*)f->fb)->field;
13975                 else
13976                         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)));
13977
13978                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13979                 return_val_if_nok (error, NULL);
13980                 type = mono_class_inflate_generic_type_checked (finst, context, error);
13981                 return_val_if_nok (error, NULL);
13982
13983                 inflated = mono_class_from_mono_type (type);
13984
13985                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13986                 ensure_complete_type (field->parent, error);
13987                 if (!is_ok (error)) {
13988                         mono_metadata_free_type (type);
13989                         return NULL;
13990                 }
13991
13992                 g_assert (result);
13993                 mono_metadata_free_type (type);
13994                 *handle_class = mono_defaults.fieldhandle_class;
13995         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13996                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13997                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13998                 return_val_if_nok (error, NULL);
13999                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14000                 return_val_if_nok (error, NULL);
14001
14002                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14003                 MonoMethod *method;
14004
14005                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14006                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14007                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14008                         method = ((MonoReflectionMethod *)c->cb)->method;
14009                 else
14010                         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)));
14011
14012                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14013                 *handle_class = mono_defaults.methodhandle_class;
14014                 mono_metadata_free_type (type);
14015         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14016                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14017                 if (m->method_args) {
14018                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14019                         return_val_if_nok (error, NULL);
14020                         if (context) {
14021                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14022                                 mono_error_assert_ok (error);
14023                         }
14024                 } else {
14025                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14026                         return_val_if_nok (error, NULL);
14027                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14028                         return_val_if_nok (error, NULL);
14029
14030                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14031                         MonoMethod *method;
14032
14033                         if (is_sre_method_builder (mono_object_class (m->mb)))
14034                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14035                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14036                                 method = ((MonoReflectionMethod *)m->mb)->method;
14037                         else
14038                                 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)));
14039
14040                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14041                         mono_metadata_free_type (type);
14042                 }
14043                 *handle_class = mono_defaults.methodhandle_class;
14044         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14045                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14046                 MonoType *mtype;
14047                 MonoClass *klass;
14048                 MonoMethod *method;
14049                 gpointer iter;
14050                 char *name;
14051
14052                 mtype = mono_reflection_type_get_handle (m->parent, error);
14053                 return_val_if_nok (error, NULL);
14054                 klass = mono_class_from_mono_type (mtype);
14055
14056                 /* Find the method */
14057
14058                 name = mono_string_to_utf8 (m->name);
14059                 iter = NULL;
14060                 while ((method = mono_class_get_methods (klass, &iter))) {
14061                         if (!strcmp (method->name, name))
14062                                 break;
14063                 }
14064                 g_free (name);
14065
14066                 // FIXME:
14067                 g_assert (method);
14068                 // FIXME: Check parameters/return value etc. match
14069
14070                 result = method;
14071                 *handle_class = mono_defaults.methodhandle_class;
14072         } else if (is_sre_array (mono_object_get_class(obj)) ||
14073                                 is_sre_byref (mono_object_get_class(obj)) ||
14074                                 is_sre_pointer (mono_object_get_class(obj))) {
14075                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14076                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14077                 return_val_if_nok (error, NULL);
14078
14079                 if (context) {
14080                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14081                         return_val_if_nok (error, NULL);
14082
14083                         result = mono_class_from_mono_type (inflated);
14084                         mono_metadata_free_type (inflated);
14085                 } else {
14086                         result = mono_class_from_mono_type (type);
14087                 }
14088                 *handle_class = mono_defaults.typehandle_class;
14089         } else {
14090                 g_print ("%s\n", obj->vtable->klass->name);
14091                 g_assert_not_reached ();
14092         }
14093         return result;
14094 }
14095
14096 #else /* DISABLE_REFLECTION_EMIT */
14097
14098 MonoArray*
14099 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14100 {
14101         g_assert_not_reached ();
14102         return NULL;
14103 }
14104
14105 void
14106 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14107 {
14108         g_assert_not_reached ();
14109 }
14110
14111 void
14112 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14113 {
14114         g_assert_not_reached ();
14115 }
14116
14117 void
14118 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14119 {
14120         g_assert_not_reached ();
14121 }
14122
14123 void
14124 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14125 {
14126         g_assert_not_reached ();
14127 }
14128
14129 void
14130 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14131 {
14132         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14133 }
14134
14135 void
14136 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14137 {
14138         g_assert_not_reached ();
14139 }
14140
14141 void
14142 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14143 {
14144         g_assert_not_reached ();
14145 }
14146
14147 MonoReflectionModule *
14148 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14149 {
14150         g_assert_not_reached ();
14151         return NULL;
14152 }
14153
14154 guint32
14155 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14156 {
14157         g_assert_not_reached ();
14158         return 0;
14159 }
14160
14161 guint32
14162 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14163 {
14164         g_assert_not_reached ();
14165         return 0;
14166 }
14167
14168 guint32
14169 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14170                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14171 {
14172         g_assert_not_reached ();
14173         return 0;
14174 }
14175
14176 void
14177 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14178 {
14179 }
14180
14181 void
14182 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14183 {
14184         g_assert_not_reached ();
14185 }
14186
14187 void
14188 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14189 {
14190         mono_error_init (error);
14191         *overrides = NULL;
14192         *num_overrides = 0;
14193 }
14194
14195 MonoReflectionEvent *
14196 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14197 {
14198         g_assert_not_reached ();
14199         return NULL;
14200 }
14201
14202 MonoReflectionType*
14203 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14204 {
14205         g_assert_not_reached ();
14206         return NULL;
14207 }
14208
14209 void
14210 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14211 {
14212         g_assert_not_reached ();
14213 }
14214
14215 MonoArray *
14216 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14217 {
14218         g_assert_not_reached ();
14219         return NULL;
14220 }
14221
14222 MonoArray *
14223 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14224 {
14225         g_assert_not_reached ();
14226         return NULL;
14227 }
14228
14229 void 
14230 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14231 {
14232 }
14233
14234 gpointer
14235 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14236 {
14237         return NULL;
14238 }
14239
14240 MonoType*
14241 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14242 {
14243         mono_error_init (error);
14244         if (!ref)
14245                 return NULL;
14246         return ref->type;
14247 }
14248
14249 void
14250 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14251 {
14252         g_assert_not_reached ();
14253 }
14254
14255 #endif /* DISABLE_REFLECTION_EMIT */
14256
14257 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14258 const static guint32 declsec_flags_map[] = {
14259         0x00000000,                                     /* empty */
14260         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14261         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14262         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14263         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14264         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14265         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14266         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14267         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14268         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14269         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14270         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14271         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14272         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14273         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14274         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14275         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14276         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14277         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14278 };
14279
14280 /*
14281  * Returns flags that includes all available security action associated to the handle.
14282  * @token: metadata token (either for a class or a method)
14283  * @image: image where resides the metadata.
14284  */
14285 static guint32
14286 mono_declsec_get_flags (MonoImage *image, guint32 token)
14287 {
14288         int index = mono_metadata_declsec_from_index (image, token);
14289         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14290         guint32 result = 0;
14291         guint32 action;
14292         int i;
14293
14294         /* HasSecurity can be present for other, not specially encoded, attributes,
14295            e.g. SuppressUnmanagedCodeSecurityAttribute */
14296         if (index < 0)
14297                 return 0;
14298
14299         for (i = index; i < t->rows; i++) {
14300                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14301
14302                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14303                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14304                         break;
14305
14306                 action = cols [MONO_DECL_SECURITY_ACTION];
14307                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14308                         result |= declsec_flags_map [action];
14309                 } else {
14310                         g_assert_not_reached ();
14311                 }
14312         }
14313         return result;
14314 }
14315
14316 /*
14317  * Get the security actions (in the form of flags) associated with the specified method.
14318  *
14319  * @method: The method for which we want the declarative security flags.
14320  * Return the declarative security flags for the method (only).
14321  *
14322  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14323  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14324  */
14325 guint32
14326 mono_declsec_flags_from_method (MonoMethod *method)
14327 {
14328         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14329                 /* FIXME: No cache (for the moment) */
14330                 guint32 idx = mono_method_get_index (method);
14331                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14332                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14333                 return mono_declsec_get_flags (method->klass->image, idx);
14334         }
14335         return 0;
14336 }
14337
14338 /*
14339  * Get the security actions (in the form of flags) associated with the specified class.
14340  *
14341  * @klass: The class for which we want the declarative security flags.
14342  * Return the declarative security flags for the class.
14343  *
14344  * Note: We cache the flags inside the MonoClass structure as this will get 
14345  *       called very often (at least for each method).
14346  */
14347 guint32
14348 mono_declsec_flags_from_class (MonoClass *klass)
14349 {
14350         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14351                 if (!klass->ext || !klass->ext->declsec_flags) {
14352                         guint32 idx;
14353
14354                         idx = mono_metadata_token_index (klass->type_token);
14355                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14356                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14357                         mono_loader_lock ();
14358                         mono_class_alloc_ext (klass);
14359                         mono_loader_unlock ();
14360                         /* we cache the flags on classes */
14361                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14362                 }
14363                 return klass->ext->declsec_flags;
14364         }
14365         return 0;
14366 }
14367
14368 /*
14369  * Get the security actions (in the form of flags) associated with the specified assembly.
14370  *
14371  * @assembly: The assembly for which we want the declarative security flags.
14372  * Return the declarative security flags for the assembly.
14373  */
14374 guint32
14375 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14376 {
14377         guint32 idx = 1; /* there is only one assembly */
14378         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14379         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14380         return mono_declsec_get_flags (assembly->image, idx);
14381 }
14382
14383
14384 /*
14385  * Fill actions for the specific index (which may either be an encoded class token or
14386  * an encoded method token) from the metadata image.
14387  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14388  */
14389 static MonoBoolean
14390 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14391         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14392 {
14393         MonoBoolean result = FALSE;
14394         MonoTableInfo *t;
14395         guint32 cols [MONO_DECL_SECURITY_SIZE];
14396         int index = mono_metadata_declsec_from_index (image, token);
14397         int i;
14398
14399         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14400         for (i = index; i < t->rows; i++) {
14401                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14402
14403                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14404                         return result;
14405
14406                 /* if present only replace (class) permissions with method permissions */
14407                 /* if empty accept either class or method permissions */
14408                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14409                         if (!actions->demand.blob) {
14410                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14411                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14412                                 actions->demand.blob = (char*) (blob + 2);
14413                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14414                                 result = TRUE;
14415                         }
14416                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14417                         if (!actions->noncasdemand.blob) {
14418                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14419                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14420                                 actions->noncasdemand.blob = (char*) (blob + 2);
14421                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14422                                 result = TRUE;
14423                         }
14424                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14425                         if (!actions->demandchoice.blob) {
14426                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14427                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14428                                 actions->demandchoice.blob = (char*) (blob + 2);
14429                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14430                                 result = TRUE;
14431                         }
14432                 }
14433         }
14434
14435         return result;
14436 }
14437
14438 static MonoBoolean
14439 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14440         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14441 {
14442         guint32 idx = mono_metadata_token_index (klass->type_token);
14443         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14444         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14445         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14446 }
14447
14448 static MonoBoolean
14449 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14450         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14451 {
14452         guint32 idx = mono_method_get_index (method);
14453         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14454         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14455         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14456 }
14457
14458 /*
14459  * Collect all actions (that requires to generate code in mini) assigned for
14460  * the specified method.
14461  * Note: Don't use the content of actions if the function return FALSE.
14462  */
14463 MonoBoolean
14464 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14465 {
14466         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14467                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14468         MonoBoolean result = FALSE;
14469         guint32 flags;
14470
14471         /* quick exit if no declarative security is present in the metadata */
14472         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14473                 return FALSE;
14474
14475         /* we want the original as the wrapper is "free" of the security informations */
14476         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14477                 method = mono_marshal_method_from_wrapper (method);
14478                 if (!method)
14479                         return FALSE;
14480         }
14481
14482         /* First we look for method-level attributes */
14483         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14484                 mono_class_init (method->klass);
14485                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14486
14487                 result = mono_declsec_get_method_demands_params (method, demands, 
14488                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14489         }
14490
14491         /* Here we use (or create) the class declarative cache to look for demands */
14492         flags = mono_declsec_flags_from_class (method->klass);
14493         if (flags & mask) {
14494                 if (!result) {
14495                         mono_class_init (method->klass);
14496                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14497                 }
14498                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14499                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14500         }
14501
14502         /* The boolean return value is used as a shortcut in case nothing needs to
14503            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14504         return result;
14505 }
14506
14507
14508 /*
14509  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14510  *
14511  * Note: Don't use the content of actions if the function return FALSE.
14512  */
14513 MonoBoolean
14514 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14515 {
14516         MonoBoolean result = FALSE;
14517         guint32 flags;
14518
14519         /* quick exit if no declarative security is present in the metadata */
14520         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14521                 return FALSE;
14522
14523         /* we want the original as the wrapper is "free" of the security informations */
14524         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14525                 method = mono_marshal_method_from_wrapper (method);
14526                 if (!method)
14527                         return FALSE;
14528         }
14529
14530         /* results are independant - zeroize both */
14531         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14532         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14533
14534         /* First we look for method-level attributes */
14535         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14536                 mono_class_init (method->klass);
14537
14538                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14539                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14540         }
14541
14542         /* Here we use (or create) the class declarative cache to look for demands */
14543         flags = mono_declsec_flags_from_class (method->klass);
14544         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14545                 mono_class_init (method->klass);
14546
14547                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14548                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14549         }
14550
14551         return result;
14552 }
14553
14554 /*
14555  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14556  *
14557  * @klass       The inherited class - this is the class that provides the security check (attributes)
14558  * @demans      
14559  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14560  * 
14561  * Note: Don't use the content of actions if the function return FALSE.
14562  */
14563 MonoBoolean
14564 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14565 {
14566         MonoBoolean result = FALSE;
14567         guint32 flags;
14568
14569         /* quick exit if no declarative security is present in the metadata */
14570         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14571                 return FALSE;
14572
14573         /* Here we use (or create) the class declarative cache to look for demands */
14574         flags = mono_declsec_flags_from_class (klass);
14575         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14576                 mono_class_init (klass);
14577                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14578
14579                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14580                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14581         }
14582
14583         return result;
14584 }
14585
14586 /*
14587  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14588  *
14589  * Note: Don't use the content of actions if the function return FALSE.
14590  */
14591 MonoBoolean
14592 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14593 {
14594         /* quick exit if no declarative security is present in the metadata */
14595         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14596                 return FALSE;
14597
14598         /* we want the original as the wrapper is "free" of the security informations */
14599         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14600                 method = mono_marshal_method_from_wrapper (method);
14601                 if (!method)
14602                         return FALSE;
14603         }
14604
14605         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14606                 mono_class_init (method->klass);
14607                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14608
14609                 return mono_declsec_get_method_demands_params (method, demands, 
14610                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14611         }
14612         return FALSE;
14613 }
14614
14615
14616 static MonoBoolean
14617 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14618 {
14619         guint32 cols [MONO_DECL_SECURITY_SIZE];
14620         MonoTableInfo *t;
14621         int i;
14622
14623         int index = mono_metadata_declsec_from_index (image, token);
14624         if (index == -1)
14625                 return FALSE;
14626
14627         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14628         for (i = index; i < t->rows; i++) {
14629                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14630
14631                 /* shortcut - index are ordered */
14632                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14633                         return FALSE;
14634
14635                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14636                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14637                         entry->blob = (char*) (metadata + 2);
14638                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14639                         return TRUE;
14640                 }
14641         }
14642
14643         return FALSE;
14644 }
14645
14646 MonoBoolean
14647 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14648 {
14649         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14650                 guint32 idx = mono_method_get_index (method);
14651                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14652                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14653                 return get_declsec_action (method->klass->image, idx, action, entry);
14654         }
14655         return FALSE;
14656 }
14657
14658 MonoBoolean
14659 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14660 {
14661         /* use cache */
14662         guint32 flags = mono_declsec_flags_from_class (klass);
14663         if (declsec_flags_map [action] & flags) {
14664                 guint32 idx = mono_metadata_token_index (klass->type_token);
14665                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14666                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14667                 return get_declsec_action (klass->image, idx, action, entry);
14668         }
14669         return FALSE;
14670 }
14671
14672 MonoBoolean
14673 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14674 {
14675         guint32 idx = 1; /* there is only one assembly */
14676         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14677         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14678
14679         return get_declsec_action (assembly->image, idx, action, entry);
14680 }
14681
14682 gboolean
14683 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14684 {
14685         MonoObject *res, *exc;
14686         void *params [1];
14687         static MonoMethod *method = NULL;
14688
14689         mono_error_init (error);
14690
14691         if (method == NULL) {
14692                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14693                 g_assert (method);
14694         }
14695
14696         /* 
14697          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14698          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14699          */
14700         g_assert (mono_class_get_ref_info (klass));
14701         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14702
14703         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14704         return_val_if_nok (error, FALSE);
14705
14706         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14707
14708         if (exc || !mono_error_ok (error)) {
14709                 mono_error_cleanup (error);
14710                 return FALSE;
14711         } else
14712                 return *(MonoBoolean*)mono_object_unbox (res);
14713 }
14714
14715 /**
14716  * mono_reflection_type_get_type:
14717  * @reftype: the System.Type object
14718  *
14719  * Returns the MonoType* associated with the C# System.Type object @reftype.
14720  */
14721 MonoType*
14722 mono_reflection_type_get_type (MonoReflectionType *reftype)
14723 {
14724         g_assert (reftype);
14725
14726         MonoError error;
14727         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14728         mono_error_assert_ok (&error);
14729         return result;
14730 }
14731
14732 /**
14733  * mono_reflection_assembly_get_assembly:
14734  * @refassembly: the System.Reflection.Assembly object
14735  *
14736  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14737  */
14738 MonoAssembly*
14739 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14740 {
14741         g_assert (refassembly);
14742
14743         return refassembly->assembly;
14744 }
14745