Merge pull request #2820 from kumpera/license-change-rebased
[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  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13 #include <config.h>
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection-internals.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internals.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
30 #include <stdio.h>
31 #include <glib.h>
32 #include <errno.h>
33 #include <time.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "image.h"
37 #include "cil-coff.h"
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/mempool-internals.h>
41 #include <mono/metadata/security-core-clr.h>
42 #include <mono/metadata/debug-helpers.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-ptr-array.h>
45 #include <mono/utils/mono-string.h>
46 #include <mono/utils/mono-error-internals.h>
47 #include <mono/utils/checked-build.h>
48
49 static gboolean is_usertype (MonoReflectionType *ref);
50 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
51
52 typedef struct {
53         char *p;
54         char *buf;
55         char *end;
56 } SigBuffer;
57
58 #define TEXT_OFFSET 512
59 #define CLI_H_SIZE 136
60 #define FILE_ALIGN 512
61 #define VIRT_ALIGN 8192
62 #define START_TEXT_RVA  0x00002000
63
64 typedef struct {
65         MonoReflectionILGen *ilgen;
66         MonoReflectionType *rtype;
67         MonoArray *parameters;
68         MonoArray *generic_params;
69         MonoGenericContainer *generic_container;
70         MonoArray *pinfo;
71         MonoArray *opt_types;
72         guint32 attrs;
73         guint32 iattrs;
74         guint32 call_conv;
75         guint32 *table_idx; /* note: it's a pointer */
76         MonoArray *code;
77         MonoObject *type;
78         MonoString *name;
79         MonoBoolean init_locals;
80         MonoBoolean skip_visibility;
81         MonoArray *return_modreq;
82         MonoArray *return_modopt;
83         MonoArray *param_modreq;
84         MonoArray *param_modopt;
85         MonoArray *permissions;
86         MonoMethod *mhandle;
87         guint32 nrefs;
88         gpointer *refs;
89         /* for PInvoke */
90         int charset, extra_flags, native_cc;
91         MonoString *dll, *dllentry;
92 } ReflectionMethodBuilder;
93
94 typedef struct {
95         guint32 owner;
96         MonoReflectionGenericParam *gparam;
97 } GenericParamTableEntry;
98
99 const unsigned char table_sizes [MONO_TABLE_NUM] = {
100         MONO_MODULE_SIZE,
101         MONO_TYPEREF_SIZE,
102         MONO_TYPEDEF_SIZE,
103         0,
104         MONO_FIELD_SIZE,
105         0,
106         MONO_METHOD_SIZE,
107         0,
108         MONO_PARAM_SIZE,
109         MONO_INTERFACEIMPL_SIZE,
110         MONO_MEMBERREF_SIZE,    /* 0x0A */
111         MONO_CONSTANT_SIZE,
112         MONO_CUSTOM_ATTR_SIZE,
113         MONO_FIELD_MARSHAL_SIZE,
114         MONO_DECL_SECURITY_SIZE,
115         MONO_CLASS_LAYOUT_SIZE,
116         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
117         MONO_STAND_ALONE_SIGNATURE_SIZE,
118         MONO_EVENT_MAP_SIZE,
119         0,
120         MONO_EVENT_SIZE,
121         MONO_PROPERTY_MAP_SIZE,
122         0,
123         MONO_PROPERTY_SIZE,
124         MONO_METHOD_SEMA_SIZE,
125         MONO_METHODIMPL_SIZE,
126         MONO_MODULEREF_SIZE,    /* 0x1A */
127         MONO_TYPESPEC_SIZE,
128         MONO_IMPLMAP_SIZE,      
129         MONO_FIELD_RVA_SIZE,
130         0,
131         0,
132         MONO_ASSEMBLY_SIZE,     /* 0x20 */
133         MONO_ASSEMBLY_PROCESSOR_SIZE,
134         MONO_ASSEMBLYOS_SIZE,
135         MONO_ASSEMBLYREF_SIZE,
136         MONO_ASSEMBLYREFPROC_SIZE,
137         MONO_ASSEMBLYREFOS_SIZE,
138         MONO_FILE_SIZE,
139         MONO_EXP_TYPE_SIZE,
140         MONO_MANIFEST_SIZE,
141         MONO_NESTED_CLASS_SIZE,
142
143         MONO_GENERICPARAM_SIZE, /* 0x2A */
144         MONO_METHODSPEC_SIZE,
145         MONO_GENPARCONSTRAINT_SIZE
146
147 };
148
149 #ifndef DISABLE_REFLECTION_EMIT
150 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
151 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
152 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
153 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
154 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
155 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
156 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
157 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
158 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
159 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
160 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
161 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
162 #endif
163
164 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
165 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
166 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
167 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
168 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
169 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
170 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
171 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
172 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
173 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
174 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
175 static gboolean is_sre_array (MonoClass *klass);
176 static gboolean is_sre_byref (MonoClass *klass);
177 static gboolean is_sre_pointer (MonoClass *klass);
178 static gboolean is_sre_type_builder (MonoClass *klass);
179 static gboolean is_sre_method_builder (MonoClass *klass);
180 static gboolean is_sre_ctor_builder (MonoClass *klass);
181 static gboolean is_sre_field_builder (MonoClass *klass);
182 static gboolean is_sr_mono_method (MonoClass *klass);
183 static gboolean is_sr_mono_cmethod (MonoClass *klass);
184 static gboolean is_sr_mono_generic_method (MonoClass *klass);
185 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
186 static gboolean is_sr_mono_field (MonoClass *klass);
187 static gboolean is_sr_mono_property (MonoClass *klass);
188 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
189 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
190
191 static gboolean type_is_reference (MonoType *type);
192
193 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
194 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
195 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
196
197 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
198 static void init_type_builder_generics (MonoObject *type);
199
200 #define RESOLVE_TYPE(type, error) do {                                  \
201         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
202 } while (0)
203 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
204         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
205         __type = mono_reflection_type_resolve_user_types (__type, error); \
206         if (mono_error_ok (error))                                      \
207                 mono_array_set (arr, MonoReflectionType*, index, __type); \
208 } while (0)
209
210 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
211
212 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
213 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
214
215 #if SIZEOF_VOID_P == 4
216 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
217 #else
218 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
219 #endif
220
221 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
222 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
223
224 /* Class lazy loading functions */
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
234 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
236 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
237 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
238 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
241 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
242 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
243 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
244
245 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
246 static GPtrArray *dynamic_images;
247 static mono_mutex_t dynamic_images_mutex;
248
249 static inline void
250 dynamic_images_lock (void)
251 {
252         mono_os_mutex_lock (&dynamic_images_mutex);
253 }
254
255 static inline void
256 dynamic_images_unlock (void)
257 {
258         mono_os_mutex_unlock (&dynamic_images_mutex);
259 }
260
261 /**
262  * mono_find_dynamic_image_owner:
263  *
264  * Find the dynamic image, if any, which a given pointer is located in the memory of.
265  */
266 MonoImage *
267 mono_find_dynamic_image_owner (void *ptr)
268 {
269         MonoImage *owner = NULL;
270         int i;
271
272         dynamic_images_lock ();
273
274         if (dynamic_images)
275         {
276                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
277                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
278                         if (mono_mempool_contains_addr (image->mempool, ptr))
279                                 owner = image;
280                 }
281         }
282
283         dynamic_images_unlock ();
284
285         return owner;
286 }
287
288 void
289 mono_reflection_init (void)
290 {
291         mono_os_mutex_init (&dynamic_images_mutex);
292 }
293
294 static inline void
295 dynamic_image_lock (MonoDynamicImage *image)
296 {
297         MONO_PREPARE_BLOCKING;
298         mono_image_lock ((MonoImage*)image);
299         MONO_FINISH_BLOCKING;
300 }
301
302 static inline void
303 dynamic_image_unlock (MonoDynamicImage *image)
304 {
305         mono_image_unlock ((MonoImage*)image);
306 }
307
308 static void
309 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
310 {
311         MONO_REQ_GC_UNSAFE_MODE;
312
313         dynamic_image_lock (assembly);
314         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
315         dynamic_image_unlock (assembly);
316 }
317
318 static MonoObject*
319 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
320 {
321         MONO_REQ_GC_UNSAFE_MODE;
322
323         MonoObject *obj;
324
325         dynamic_image_lock (assembly);
326         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
327         dynamic_image_unlock (assembly);
328
329         return obj;
330 }
331
332 static void
333 sigbuffer_init (SigBuffer *buf, int size)
334 {
335         MONO_REQ_GC_NEUTRAL_MODE;
336
337         buf->buf = (char *)g_malloc (size);
338         buf->p = buf->buf;
339         buf->end = buf->buf + size;
340 }
341
342 static void
343 sigbuffer_make_room (SigBuffer *buf, int size)
344 {
345         MONO_REQ_GC_NEUTRAL_MODE;
346
347         if (buf->end - buf->p < size) {
348                 int new_size = buf->end - buf->buf + size + 32;
349                 char *p = (char *)g_realloc (buf->buf, new_size);
350                 size = buf->p - buf->buf;
351                 buf->buf = p;
352                 buf->p = p + size;
353                 buf->end = buf->buf + new_size;
354         }
355 }
356
357 static void
358 sigbuffer_add_value (SigBuffer *buf, guint32 val)
359 {
360         MONO_REQ_GC_NEUTRAL_MODE;
361
362         sigbuffer_make_room (buf, 6);
363         mono_metadata_encode_value (val, buf->p, &buf->p);
364 }
365
366 static void
367 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
368 {
369         MONO_REQ_GC_NEUTRAL_MODE;
370
371         sigbuffer_make_room (buf, 1);
372         buf->p [0] = val;
373         buf->p++;
374 }
375
376 static void
377 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
378 {
379         MONO_REQ_GC_NEUTRAL_MODE;
380
381         sigbuffer_make_room (buf, size);
382         memcpy (buf->p, p, size);
383         buf->p += size;
384 }
385
386 static void
387 sigbuffer_free (SigBuffer *buf)
388 {
389         MONO_REQ_GC_NEUTRAL_MODE;
390
391         g_free (buf->buf);
392 }
393
394 #ifndef DISABLE_REFLECTION_EMIT
395 /**
396  * mp_g_alloc:
397  *
398  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
399  * from the C heap.
400  */
401 static gpointer
402 image_g_malloc (MonoImage *image, guint size)
403 {
404         MONO_REQ_GC_NEUTRAL_MODE;
405
406         if (image)
407                 return mono_image_alloc (image, size);
408         else
409                 return g_malloc (size);
410 }
411 #endif /* !DISABLE_REFLECTION_EMIT */
412
413 /**
414  * image_g_alloc0:
415  *
416  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
417  * from the C heap.
418  */
419 static gpointer
420 image_g_malloc0 (MonoImage *image, guint size)
421 {
422         MONO_REQ_GC_NEUTRAL_MODE;
423
424         if (image)
425                 return mono_image_alloc0 (image, size);
426         else
427                 return g_malloc0 (size);
428 }
429
430 /**
431  * image_g_free:
432  * @image: a MonoImage
433  * @ptr: pointer
434  *
435  * If @image is NULL, free @ptr, otherwise do nothing.
436  */
437 static void
438 image_g_free (MonoImage *image, gpointer ptr)
439 {
440         if (image == NULL)
441                 g_free (ptr);
442 }
443
444 #ifndef DISABLE_REFLECTION_EMIT
445 static char*
446 image_strdup (MonoImage *image, const char *s)
447 {
448         MONO_REQ_GC_NEUTRAL_MODE;
449
450         if (image)
451                 return mono_image_strdup (image, s);
452         else
453                 return g_strdup (s);
454 }
455 #endif
456
457 #define image_g_new(image,struct_type, n_structs)               \
458     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460 #define image_g_new0(image,struct_type, n_structs)              \
461     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
462
463
464 static void
465 alloc_table (MonoDynamicTable *table, guint nrows)
466 {
467         MONO_REQ_GC_NEUTRAL_MODE;
468
469         table->rows = nrows;
470         g_assert (table->columns);
471         if (nrows + 1 >= table->alloc_rows) {
472                 while (nrows + 1 >= table->alloc_rows) {
473                         if (table->alloc_rows == 0)
474                                 table->alloc_rows = 16;
475                         else
476                                 table->alloc_rows *= 2;
477                 }
478
479                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
480         }
481 }
482
483 static void
484 make_room_in_stream (MonoDynamicStream *stream, int size)
485 {
486         MONO_REQ_GC_NEUTRAL_MODE;
487
488         if (size <= stream->alloc_size)
489                 return;
490         
491         while (stream->alloc_size <= size) {
492                 if (stream->alloc_size < 4096)
493                         stream->alloc_size = 4096;
494                 else
495                         stream->alloc_size *= 2;
496         }
497         
498         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
499 }
500
501 static guint32
502 string_heap_insert (MonoDynamicStream *sh, const char *str)
503 {
504         MONO_REQ_GC_NEUTRAL_MODE;
505
506         guint32 idx;
507         guint32 len;
508         gpointer oldkey, oldval;
509
510         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
511                 return GPOINTER_TO_UINT (oldval);
512
513         len = strlen (str) + 1;
514         idx = sh->index;
515         
516         make_room_in_stream (sh, idx + len);
517
518         /*
519          * We strdup the string even if we already copy them in sh->data
520          * so that the string pointers in the hash remain valid even if
521          * we need to realloc sh->data. We may want to avoid that later.
522          */
523         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
524         memcpy (sh->data + idx, str, len);
525         sh->index += len;
526         return idx;
527 }
528
529 static guint32
530 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
531 {
532         MONO_REQ_GC_UNSAFE_MODE;
533
534         char *name = mono_string_to_utf8 (str);
535         guint32 idx;
536         idx = string_heap_insert (sh, name);
537         g_free (name);
538         return idx;
539 }
540
541 #ifndef DISABLE_REFLECTION_EMIT
542 static void
543 string_heap_init (MonoDynamicStream *sh)
544 {
545         MONO_REQ_GC_NEUTRAL_MODE;
546
547         sh->index = 0;
548         sh->alloc_size = 4096;
549         sh->data = (char *)g_malloc (4096);
550         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
551         string_heap_insert (sh, "");
552 }
553 #endif
554
555 static guint32
556 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
557 {
558         MONO_REQ_GC_NEUTRAL_MODE;
559
560         guint32 idx;
561         
562         make_room_in_stream (stream, stream->index + len);
563         memcpy (stream->data + stream->index, data, len);
564         idx = stream->index;
565         stream->index += len;
566         /* 
567          * align index? Not without adding an additional param that controls it since
568          * we may store a blob value in pieces.
569          */
570         return idx;
571 }
572
573 static guint32
574 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
575 {
576         MONO_REQ_GC_NEUTRAL_MODE;
577
578         guint32 idx;
579         
580         make_room_in_stream (stream, stream->index + len);
581         memset (stream->data + stream->index, 0, len);
582         idx = stream->index;
583         stream->index += len;
584         return idx;
585 }
586
587 static void
588 stream_data_align (MonoDynamicStream *stream)
589 {
590         MONO_REQ_GC_NEUTRAL_MODE;
591
592         char buf [4] = {0};
593         guint32 count = stream->index % 4;
594
595         /* we assume the stream data will be aligned */
596         if (count)
597                 mono_image_add_stream_data (stream, buf, 4 - count);
598 }
599
600 #ifndef DISABLE_REFLECTION_EMIT
601 static int
602 mono_blob_entry_hash (const char* str)
603 {
604         MONO_REQ_GC_NEUTRAL_MODE;
605
606         guint len, h;
607         const char *end;
608         len = mono_metadata_decode_blob_size (str, &str);
609         if (len > 0) {
610                 end = str + len;
611                 h = *str;
612                 for (str += 1; str < end; str++)
613                         h = (h << 5) - h + *str;
614                 return h;
615         } else {
616                 return 0;
617         }
618 }
619
620 static gboolean
621 mono_blob_entry_equal (const char *str1, const char *str2) {
622         MONO_REQ_GC_NEUTRAL_MODE;
623
624         int len, len2;
625         const char *end1;
626         const char *end2;
627         len = mono_metadata_decode_blob_size (str1, &end1);
628         len2 = mono_metadata_decode_blob_size (str2, &end2);
629         if (len != len2)
630                 return 0;
631         return memcmp (end1, end2, len) == 0;
632 }
633 #endif
634 static guint32
635 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
636 {
637         MONO_REQ_GC_NEUTRAL_MODE;
638
639         guint32 idx;
640         char *copy;
641         gpointer oldkey, oldval;
642
643         copy = (char *)g_malloc (s1+s2);
644         memcpy (copy, b1, s1);
645         memcpy (copy + s1, b2, s2);
646         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
647                 g_free (copy);
648                 idx = GPOINTER_TO_UINT (oldval);
649         } else {
650                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
651                 mono_image_add_stream_data (&assembly->blob, b2, s2);
652                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
653         }
654         return idx;
655 }
656
657 static guint32
658 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
659 {
660         MONO_REQ_GC_NEUTRAL_MODE;
661
662         char blob_size [8];
663         char *b = blob_size;
664         guint32 size = buf->p - buf->buf;
665         /* store length */
666         g_assert (size <= (buf->end - buf->buf));
667         mono_metadata_encode_value (size, b, &b);
668         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
669 }
670
671 /*
672  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
673  * dest may be misaligned.
674  */
675 static void
676 swap_with_size (char *dest, const char* val, int len, int nelem) {
677         MONO_REQ_GC_NEUTRAL_MODE;
678 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
679         int elem;
680
681         for (elem = 0; elem < nelem; ++elem) {
682                 switch (len) {
683                 case 1:
684                         *dest = *val;
685                         break;
686                 case 2:
687                         dest [0] = val [1];
688                         dest [1] = val [0];
689                         break;
690                 case 4:
691                         dest [0] = val [3];
692                         dest [1] = val [2];
693                         dest [2] = val [1];
694                         dest [3] = val [0];
695                         break;
696                 case 8:
697                         dest [0] = val [7];
698                         dest [1] = val [6];
699                         dest [2] = val [5];
700                         dest [3] = val [4];
701                         dest [4] = val [3];
702                         dest [5] = val [2];
703                         dest [6] = val [1];
704                         dest [7] = val [0];
705                         break;
706                 default:
707                         g_assert_not_reached ();
708                 }
709                 dest += len;
710                 val += len;
711         }
712 #else
713         memcpy (dest, val, len * nelem);
714 #endif
715 }
716
717 static guint32
718 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
719 {
720         MONO_REQ_GC_UNSAFE_MODE;
721         
722         char blob_size [64];
723         char *b = blob_size;
724         guint32 idx = 0, len;
725
726         len = str->length * 2;
727         mono_metadata_encode_value (len, b, &b);
728 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
729         {
730                 char *swapped = g_malloc (2 * mono_string_length (str));
731                 const char *p = (const char*)mono_string_chars (str);
732
733                 swap_with_size (swapped, p, 2, mono_string_length (str));
734                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
735                 g_free (swapped);
736         }
737 #else
738         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
739 #endif
740         return idx;
741 }
742
743 #ifndef DISABLE_REFLECTION_EMIT
744 static MonoClass *
745 default_class_from_mono_type (MonoType *type)
746 {
747         MONO_REQ_GC_NEUTRAL_MODE;
748
749         switch (type->type) {
750         case MONO_TYPE_OBJECT:
751                 return mono_defaults.object_class;
752         case MONO_TYPE_VOID:
753                 return mono_defaults.void_class;
754         case MONO_TYPE_BOOLEAN:
755                 return mono_defaults.boolean_class;
756         case MONO_TYPE_CHAR:
757                 return mono_defaults.char_class;
758         case MONO_TYPE_I1:
759                 return mono_defaults.sbyte_class;
760         case MONO_TYPE_U1:
761                 return mono_defaults.byte_class;
762         case MONO_TYPE_I2:
763                 return mono_defaults.int16_class;
764         case MONO_TYPE_U2:
765                 return mono_defaults.uint16_class;
766         case MONO_TYPE_I4:
767                 return mono_defaults.int32_class;
768         case MONO_TYPE_U4:
769                 return mono_defaults.uint32_class;
770         case MONO_TYPE_I:
771                 return mono_defaults.int_class;
772         case MONO_TYPE_U:
773                 return mono_defaults.uint_class;
774         case MONO_TYPE_I8:
775                 return mono_defaults.int64_class;
776         case MONO_TYPE_U8:
777                 return mono_defaults.uint64_class;
778         case MONO_TYPE_R4:
779                 return mono_defaults.single_class;
780         case MONO_TYPE_R8:
781                 return mono_defaults.double_class;
782         case MONO_TYPE_STRING:
783                 return mono_defaults.string_class;
784         default:
785                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
786                 g_assert_not_reached ();
787         }
788         
789         return NULL;
790 }
791 #endif
792
793 /*
794  * mono_class_get_ref_info:
795  *
796  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
797  */
798 gpointer
799 mono_class_get_ref_info (MonoClass *klass)
800 {
801         MONO_REQ_GC_UNSAFE_MODE;
802
803         if (klass->ref_info_handle == 0)
804                 return NULL;
805         else
806                 return mono_gchandle_get_target (klass->ref_info_handle);
807 }
808
809 void
810 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
811 {
812         MONO_REQ_GC_UNSAFE_MODE;
813
814         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
815         g_assert (klass->ref_info_handle != 0);
816 }
817
818 void
819 mono_class_free_ref_info (MonoClass *klass)
820 {
821         MONO_REQ_GC_NEUTRAL_MODE;
822
823         if (klass->ref_info_handle) {
824                 mono_gchandle_free (klass->ref_info_handle);
825                 klass->ref_info_handle = 0;
826         }
827 }
828
829 static void
830 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
831 {
832         MONO_REQ_GC_NEUTRAL_MODE;
833
834         int i;
835         MonoGenericInst *class_inst;
836         MonoClass *klass;
837
838         g_assert (gclass);
839
840         class_inst = gclass->context.class_inst;
841
842         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
843         klass = gclass->container_class;
844         sigbuffer_add_value (buf, klass->byval_arg.type);
845         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
846
847         sigbuffer_add_value (buf, class_inst->type_argc);
848         for (i = 0; i < class_inst->type_argc; ++i)
849                 encode_type (assembly, class_inst->type_argv [i], buf);
850
851 }
852
853 static void
854 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
855 {
856         MONO_REQ_GC_NEUTRAL_MODE;
857
858         if (!type) {
859                 g_assert_not_reached ();
860                 return;
861         }
862                 
863         if (type->byref)
864                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
865
866         switch (type->type){
867         case MONO_TYPE_VOID:
868         case MONO_TYPE_BOOLEAN:
869         case MONO_TYPE_CHAR:
870         case MONO_TYPE_I1:
871         case MONO_TYPE_U1:
872         case MONO_TYPE_I2:
873         case MONO_TYPE_U2:
874         case MONO_TYPE_I4:
875         case MONO_TYPE_U4:
876         case MONO_TYPE_I8:
877         case MONO_TYPE_U8:
878         case MONO_TYPE_R4:
879         case MONO_TYPE_R8:
880         case MONO_TYPE_I:
881         case MONO_TYPE_U:
882         case MONO_TYPE_STRING:
883         case MONO_TYPE_OBJECT:
884         case MONO_TYPE_TYPEDBYREF:
885                 sigbuffer_add_value (buf, type->type);
886                 break;
887         case MONO_TYPE_PTR:
888                 sigbuffer_add_value (buf, type->type);
889                 encode_type (assembly, type->data.type, buf);
890                 break;
891         case MONO_TYPE_SZARRAY:
892                 sigbuffer_add_value (buf, type->type);
893                 encode_type (assembly, &type->data.klass->byval_arg, buf);
894                 break;
895         case MONO_TYPE_VALUETYPE:
896         case MONO_TYPE_CLASS: {
897                 MonoClass *k = mono_class_from_mono_type (type);
898
899                 if (k->generic_container) {
900                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
901                         encode_generic_class (assembly, gclass, buf);
902                 } else {
903                         /*
904                          * Make sure we use the correct type.
905                          */
906                         sigbuffer_add_value (buf, k->byval_arg.type);
907                         /*
908                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
909                          * otherwise two typerefs could point to the same type, leading to
910                          * verification errors.
911                          */
912                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
913                 }
914                 break;
915         }
916         case MONO_TYPE_ARRAY:
917                 sigbuffer_add_value (buf, type->type);
918                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
919                 sigbuffer_add_value (buf, type->data.array->rank);
920                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
921                 sigbuffer_add_value (buf, 0);
922                 break;
923         case MONO_TYPE_GENERICINST:
924                 encode_generic_class (assembly, type->data.generic_class, buf);
925                 break;
926         case MONO_TYPE_VAR:
927         case MONO_TYPE_MVAR:
928                 sigbuffer_add_value (buf, type->type);
929                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
930                 break;
931         default:
932                 g_error ("need to encode type %x", type->type);
933         }
934 }
935
936 static void
937 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
938 {
939         MONO_REQ_GC_UNSAFE_MODE;
940
941         mono_error_init (error);
942
943         if (!type) {
944                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
945                 return;
946         }
947
948         MonoType *t = mono_reflection_type_get_handle (type, error);
949         return_if_nok (error);
950         encode_type (assembly, t, buf);
951 }
952
953 static void
954 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
955 {
956         MONO_REQ_GC_UNSAFE_MODE;
957
958         int i;
959
960         mono_error_init (error);
961
962         if (modreq) {
963                 for (i = 0; i < mono_array_length (modreq); ++i) {
964                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
965                         return_if_nok (error);
966                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
967                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
968                 }
969         }
970         if (modopt) {
971                 for (i = 0; i < mono_array_length (modopt); ++i) {
972                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
973                         return_if_nok (error);
974                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
975                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
976                 }
977         }
978 }
979
980 #ifndef DISABLE_REFLECTION_EMIT
981 static guint32
982 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
983 {
984         MONO_REQ_GC_UNSAFE_MODE;
985
986         SigBuffer buf;
987         int i;
988         guint32 nparams =  sig->param_count;
989         guint32 idx;
990
991         if (!assembly->save)
992                 return 0;
993
994         sigbuffer_init (&buf, 32);
995         /*
996          * FIXME: vararg, explicit_this, differenc call_conv values...
997          */
998         idx = sig->call_convention;
999         if (sig->hasthis)
1000                 idx |= 0x20; /* hasthis */
1001         if (sig->generic_param_count)
1002                 idx |= 0x10; /* generic */
1003         sigbuffer_add_byte (&buf, idx);
1004         if (sig->generic_param_count)
1005                 sigbuffer_add_value (&buf, sig->generic_param_count);
1006         sigbuffer_add_value (&buf, nparams);
1007         encode_type (assembly, sig->ret, &buf);
1008         for (i = 0; i < nparams; ++i) {
1009                 if (i == sig->sentinelpos)
1010                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1011                 encode_type (assembly, sig->params [i], &buf);
1012         }
1013         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1014         sigbuffer_free (&buf);
1015         return idx;
1016 }
1017 #endif
1018
1019 static guint32
1020 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1021 {
1022         MONO_REQ_GC_UNSAFE_MODE;
1023
1024         mono_error_init (error);
1025
1026         /*
1027          * FIXME: reuse code from method_encode_signature().
1028          */
1029         SigBuffer buf;
1030         int i;
1031         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1032         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1033         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1034         guint32 idx;
1035
1036         sigbuffer_init (&buf, 32);
1037         /* LAMESPEC: all the call conv spec is foobared */
1038         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1039         if (mb->call_conv & 2)
1040                 idx |= 0x5; /* vararg */
1041         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1042                 idx |= 0x20; /* hasthis */
1043         if (ngparams)
1044                 idx |= 0x10; /* generic */
1045         sigbuffer_add_byte (&buf, idx);
1046         if (ngparams)
1047                 sigbuffer_add_value (&buf, ngparams);
1048         sigbuffer_add_value (&buf, nparams + notypes);
1049         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1050         if (!is_ok (error))
1051                 goto leave;
1052         encode_reflection_type (assembly, mb->rtype, &buf, error);
1053         if (!is_ok (error))
1054                 goto leave;
1055         for (i = 0; i < nparams; ++i) {
1056                 MonoArray *modreq = NULL;
1057                 MonoArray *modopt = NULL;
1058                 MonoReflectionType *pt;
1059
1060                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1061                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1062                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1063                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1064                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1065                 if (!is_ok (error))
1066                         goto leave;
1067                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1068                 encode_reflection_type (assembly, pt, &buf, error);
1069                 if (!is_ok (error))
1070                         goto leave;
1071         }
1072         if (notypes)
1073                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1074         for (i = 0; i < notypes; ++i) {
1075                 MonoReflectionType *pt;
1076
1077                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1078                 encode_reflection_type (assembly, pt, &buf, error);
1079                 if (!is_ok (error))
1080                         goto leave;
1081         }
1082
1083         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1084 leave:
1085         sigbuffer_free (&buf);
1086         return idx;
1087 }
1088
1089 static guint32
1090 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1091 {
1092         MONO_REQ_GC_UNSAFE_MODE;
1093
1094         mono_error_init (error);
1095
1096         MonoDynamicTable *table;
1097         guint32 *values;
1098         guint32 idx, sig_idx;
1099         guint nl = mono_array_length (ilgen->locals);
1100         SigBuffer buf;
1101         int i;
1102
1103         sigbuffer_init (&buf, 32);
1104         sigbuffer_add_value (&buf, 0x07);
1105         sigbuffer_add_value (&buf, nl);
1106         for (i = 0; i < nl; ++i) {
1107                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1108                 
1109                 if (lb->is_pinned)
1110                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1111                 
1112                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1113                 if (!is_ok (error)) {
1114                         sigbuffer_free (&buf);
1115                         return 0;
1116                 }
1117         }
1118         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1119         sigbuffer_free (&buf);
1120
1121         if (assembly->standalonesig_cache == NULL)
1122                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1123         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1124         if (idx)
1125                 return idx;
1126
1127         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1128         idx = table->next_idx ++;
1129         table->rows ++;
1130         alloc_table (table, table->rows);
1131         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1132
1133         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1134
1135         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1136
1137         return idx;
1138 }
1139
1140 static guint32
1141 method_count_clauses (MonoReflectionILGen *ilgen)
1142 {
1143         MONO_REQ_GC_UNSAFE_MODE;
1144
1145         guint32 num_clauses = 0;
1146         int i;
1147
1148         MonoILExceptionInfo *ex_info;
1149         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1150                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1151                 if (ex_info->handlers)
1152                         num_clauses += mono_array_length (ex_info->handlers);
1153                 else
1154                         num_clauses++;
1155         }
1156
1157         return num_clauses;
1158 }
1159
1160 #ifndef DISABLE_REFLECTION_EMIT
1161 static MonoExceptionClause*
1162 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1163 {
1164         MONO_REQ_GC_UNSAFE_MODE;
1165
1166         mono_error_init (error);
1167
1168         MonoExceptionClause *clauses;
1169         MonoExceptionClause *clause;
1170         MonoILExceptionInfo *ex_info;
1171         MonoILExceptionBlock *ex_block;
1172         guint32 finally_start;
1173         int i, j, clause_index;;
1174
1175         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1176
1177         clause_index = 0;
1178         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1179                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1180                 finally_start = ex_info->start + ex_info->len;
1181                 if (!ex_info->handlers)
1182                         continue;
1183                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1184                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1185                         clause = &(clauses [clause_index]);
1186
1187                         clause->flags = ex_block->type;
1188                         clause->try_offset = ex_info->start;
1189
1190                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1191                                 clause->try_len = finally_start - ex_info->start;
1192                         else
1193                                 clause->try_len = ex_info->len;
1194                         clause->handler_offset = ex_block->start;
1195                         clause->handler_len = ex_block->len;
1196                         if (ex_block->extype) {
1197                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1198
1199                                 if (!is_ok (error)) {
1200                                         image_g_free (image, clauses);
1201                                         return NULL;
1202                                 }
1203                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1204                         } else {
1205                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1206                                         clause->data.filter_offset = ex_block->filter_offset;
1207                                 else
1208                                         clause->data.filter_offset = 0;
1209                         }
1210                         finally_start = ex_block->start + ex_block->len;
1211
1212                         clause_index ++;
1213                 }
1214         }
1215
1216         return clauses;
1217 }
1218 #endif /* !DISABLE_REFLECTION_EMIT */
1219
1220 /**
1221  * method_encode_code:
1222  *
1223  * @assembly the assembly
1224  * @mb the managed MethodBuilder
1225  * @error set on error
1226  *
1227  * Note that the return value is not sensible if @error is set.
1228  */
1229 static guint32
1230 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1231 {
1232         MONO_REQ_GC_UNSAFE_MODE;
1233
1234         char flags = 0;
1235         guint32 idx;
1236         guint32 code_size;
1237         gint32 max_stack, i;
1238         gint32 num_locals = 0;
1239         gint32 num_exception = 0;
1240         gint maybe_small;
1241         guint32 fat_flags;
1242         char fat_header [12];
1243         guint32 int_value;
1244         guint16 short_value;
1245         guint32 local_sig = 0;
1246         guint32 header_size = 12;
1247         MonoArray *code;
1248
1249         mono_error_init (error);
1250
1251         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1252                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1253                 return 0;
1254
1255         /*if (mb->name)
1256                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1257         if (mb->ilgen) {
1258                 code = mb->ilgen->code;
1259                 code_size = mb->ilgen->code_len;
1260                 max_stack = mb->ilgen->max_stack;
1261                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1262                 if (mb->ilgen->ex_handlers)
1263                         num_exception = method_count_clauses (mb->ilgen);
1264         } else {
1265                 code = mb->code;
1266                 if (code == NULL){
1267                         char *name = mono_string_to_utf8 (mb->name);
1268                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1269                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1270                         g_free (str);
1271                         g_free (name);
1272                         return 0;
1273                 }
1274
1275                 code_size = mono_array_length (code);
1276                 max_stack = 8; /* we probably need to run a verifier on the code... */
1277         }
1278
1279         stream_data_align (&assembly->code);
1280
1281         /* check for exceptions, maxstack, locals */
1282         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1283         if (maybe_small) {
1284                 if (code_size < 64 && !(code_size & 1)) {
1285                         flags = (code_size << 2) | 0x2;
1286                 } else if (code_size < 32 && (code_size & 1)) {
1287                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1288                 } else {
1289                         goto fat_header;
1290                 }
1291                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1292                 /* add to the fixup todo list */
1293                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1294                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1295                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1296                 return assembly->text_rva + idx;
1297         } 
1298 fat_header:
1299         if (num_locals) {
1300                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1301                 return_val_if_nok (error, 0);
1302         }
1303         /* 
1304          * FIXME: need to set also the header size in fat_flags.
1305          * (and more sects and init locals flags)
1306          */
1307         fat_flags =  0x03;
1308         if (num_exception)
1309                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1310         if (mb->init_locals)
1311                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1312         fat_header [0] = fat_flags;
1313         fat_header [1] = (header_size / 4 ) << 4;
1314         short_value = GUINT16_TO_LE (max_stack);
1315         memcpy (fat_header + 2, &short_value, 2);
1316         int_value = GUINT32_TO_LE (code_size);
1317         memcpy (fat_header + 4, &int_value, 4);
1318         int_value = GUINT32_TO_LE (local_sig);
1319         memcpy (fat_header + 8, &int_value, 4);
1320         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1321         /* add to the fixup todo list */
1322         if (mb->ilgen && mb->ilgen->num_token_fixups)
1323                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1324         
1325         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1326         if (num_exception) {
1327                 unsigned char sheader [4];
1328                 MonoILExceptionInfo * ex_info;
1329                 MonoILExceptionBlock * ex_block;
1330                 int j;
1331
1332                 stream_data_align (&assembly->code);
1333                 /* always use fat format for now */
1334                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1335                 num_exception *= 6 * sizeof (guint32);
1336                 num_exception += 4; /* include the size of the header */
1337                 sheader [1] = num_exception & 0xff;
1338                 sheader [2] = (num_exception >> 8) & 0xff;
1339                 sheader [3] = (num_exception >> 16) & 0xff;
1340                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1341                 /* fat header, so we are already aligned */
1342                 /* reverse order */
1343                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1344                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1345                         if (ex_info->handlers) {
1346                                 int finally_start = ex_info->start + ex_info->len;
1347                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1348                                         guint32 val;
1349                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1350                                         /* the flags */
1351                                         val = GUINT32_TO_LE (ex_block->type);
1352                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353                                         /* try offset */
1354                                         val = GUINT32_TO_LE (ex_info->start);
1355                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1356                                         /* need fault, too, probably */
1357                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1358                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1359                                         else
1360                                                 val = GUINT32_TO_LE (ex_info->len);
1361                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362                                         /* handler offset */
1363                                         val = GUINT32_TO_LE (ex_block->start);
1364                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365                                         /* handler len */
1366                                         val = GUINT32_TO_LE (ex_block->len);
1367                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1368                                         finally_start = ex_block->start + ex_block->len;
1369                                         if (ex_block->extype) {
1370                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1371                                                 return_val_if_nok (error, 0);
1372
1373                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1374                                         } else {
1375                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1376                                                         val = ex_block->filter_offset;
1377                                                 else
1378                                                         val = 0;
1379                                         }
1380                                         val = GUINT32_TO_LE (val);
1381                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1382                                         /*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", 
1383                                                         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);*/
1384                                 }
1385                         } else {
1386                                 g_error ("No clauses for ex info block %d", i);
1387                         }
1388                 }
1389         }
1390         return assembly->text_rva + idx;
1391 }
1392
1393 static guint32
1394 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1395 {
1396         MONO_REQ_GC_NEUTRAL_MODE;
1397
1398         int i;
1399         MonoDynamicTable *table;
1400         guint32 *values;
1401         
1402         table = &assembly->tables [table_idx];
1403
1404         g_assert (col < table->columns);
1405
1406         values = table->values + table->columns;
1407         for (i = 1; i <= table->rows; ++i) {
1408                 if (values [col] == token)
1409                         return i;
1410                 values += table->columns;
1411         }
1412         return 0;
1413 }
1414
1415 /*
1416  * LOCKING: Acquires the loader lock. 
1417  */
1418 static MonoCustomAttrInfo*
1419 lookup_custom_attr (MonoImage *image, gpointer member)
1420 {
1421         MONO_REQ_GC_NEUTRAL_MODE;
1422
1423         MonoCustomAttrInfo* res;
1424
1425         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1426
1427         if (!res)
1428                 return NULL;
1429
1430         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1431         res->cached = 0;
1432         return res;
1433 }
1434
1435 static gboolean
1436 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1437 {
1438         MONO_REQ_GC_UNSAFE_MODE;
1439
1440         /* FIXME: Need to do more checks */
1441         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1442                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1443
1444                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1445                         return FALSE;
1446         }
1447
1448         return TRUE;
1449 }
1450
1451 static MonoCustomAttrInfo*
1452 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1453 {
1454         MONO_REQ_GC_UNSAFE_MODE;
1455
1456         int i, index, count, not_visible;
1457         MonoCustomAttrInfo *ainfo;
1458         MonoReflectionCustomAttr *cattr;
1459
1460         if (!cattrs)
1461                 return NULL;
1462         /* FIXME: check in assembly the Run flag is set */
1463
1464         count = mono_array_length (cattrs);
1465
1466         /* Skip nonpublic attributes since MS.NET seems to do the same */
1467         /* FIXME: This needs to be done more globally */
1468         not_visible = 0;
1469         for (i = 0; i < count; ++i) {
1470                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1471                 if (!custom_attr_visible (image, cattr))
1472                         not_visible ++;
1473         }
1474         count -= not_visible;
1475
1476         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1477
1478         ainfo->image = image;
1479         ainfo->num_attrs = count;
1480         ainfo->cached = alloc_img != NULL;
1481         index = 0;
1482         for (i = 0; i < count; ++i) {
1483                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1484                 if (custom_attr_visible (image, cattr)) {
1485                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1486                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1487                         ainfo->attrs [index].ctor = cattr->ctor->method;
1488                         ainfo->attrs [index].data = saved;
1489                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1490                         index ++;
1491                 }
1492         }
1493
1494         return ainfo;
1495 }
1496
1497 #ifndef DISABLE_REFLECTION_EMIT
1498 /*
1499  * LOCKING: Acquires the loader lock. 
1500  */
1501 static void
1502 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1503 {
1504         MONO_REQ_GC_UNSAFE_MODE;
1505
1506         MonoCustomAttrInfo *ainfo, *tmp;
1507
1508         if (!cattrs || !mono_array_length (cattrs))
1509                 return;
1510
1511         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1512
1513         mono_loader_lock ();
1514         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1515         if (tmp)
1516                 mono_custom_attrs_free (tmp);
1517         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1518         mono_loader_unlock ();
1519
1520 }
1521 #endif
1522
1523 void
1524 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1525 {
1526         MONO_REQ_GC_NEUTRAL_MODE;
1527
1528         if (ainfo && !ainfo->cached)
1529                 g_free (ainfo);
1530 }
1531
1532 /*
1533  * idx is the table index of the object
1534  * type is one of MONO_CUSTOM_ATTR_*
1535  */
1536 static gboolean
1537 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1538 {
1539         MONO_REQ_GC_UNSAFE_MODE;
1540
1541         MonoDynamicTable *table;
1542         MonoReflectionCustomAttr *cattr;
1543         guint32 *values;
1544         guint32 count, i, token;
1545         char blob_size [6];
1546         char *p = blob_size;
1547         
1548         mono_error_init (error);
1549
1550         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1551         if (!cattrs)
1552                 return TRUE;
1553         count = mono_array_length (cattrs);
1554         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1555         table->rows += count;
1556         alloc_table (table, table->rows);
1557         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1558         idx <<= MONO_CUSTOM_ATTR_BITS;
1559         idx |= type;
1560         for (i = 0; i < count; ++i) {
1561                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1562                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1563                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1564                 if (!mono_error_ok (error)) goto fail;
1565                 type = mono_metadata_token_index (token);
1566                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1567                 switch (mono_metadata_token_table (token)) {
1568                 case MONO_TABLE_METHOD:
1569                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1570                         /*
1571                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1572                          * method, not the one returned by mono_image_create_token ().
1573                          */
1574                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1575                         break;
1576                 case MONO_TABLE_MEMBERREF:
1577                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1578                         break;
1579                 default:
1580                         g_warning ("got wrong token in custom attr");
1581                         continue;
1582                 }
1583                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1584                 p = blob_size;
1585                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1586                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1587                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1588                 values += MONO_CUSTOM_ATTR_SIZE;
1589                 ++table->next_idx;
1590         }
1591
1592         return TRUE;
1593
1594 fail:
1595         return FALSE;
1596 }
1597
1598 static void
1599 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1600 {
1601         MONO_REQ_GC_UNSAFE_MODE;
1602
1603         MonoDynamicTable *table;
1604         guint32 *values;
1605         guint32 count, i, idx;
1606         MonoReflectionPermissionSet *perm;
1607
1608         if (!permissions)
1609                 return;
1610
1611         count = mono_array_length (permissions);
1612         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1613         table->rows += count;
1614         alloc_table (table, table->rows);
1615
1616         for (i = 0; i < mono_array_length (permissions); ++i) {
1617                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1618
1619                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1620
1621                 idx = mono_metadata_token_index (parent_token);
1622                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1623                 switch (mono_metadata_token_table (parent_token)) {
1624                 case MONO_TABLE_TYPEDEF:
1625                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1626                         break;
1627                 case MONO_TABLE_METHOD:
1628                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1629                         break;
1630                 case MONO_TABLE_ASSEMBLY:
1631                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1632                         break;
1633                 default:
1634                         g_assert_not_reached ();
1635                 }
1636
1637                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1638                 values [MONO_DECL_SECURITY_PARENT] = idx;
1639                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1640
1641                 ++table->next_idx;
1642         }
1643 }
1644
1645 /*
1646  * Fill in the MethodDef and ParamDef tables for a method.
1647  * This is used for both normal methods and constructors.
1648  */
1649 static gboolean
1650 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1651 {
1652         MONO_REQ_GC_UNSAFE_MODE;
1653
1654         MonoDynamicTable *table;
1655         guint32 *values;
1656         guint i, count;
1657
1658         mono_error_init (error);
1659
1660         /* room in this table is already allocated */
1661         table = &assembly->tables [MONO_TABLE_METHOD];
1662         *mb->table_idx = table->next_idx ++;
1663         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1664         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1665         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1666         values [MONO_METHOD_FLAGS] = mb->attrs;
1667         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1668         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1669         return_val_if_nok (error, FALSE);
1670         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1671         return_val_if_nok (error, FALSE);
1672
1673         table = &assembly->tables [MONO_TABLE_PARAM];
1674         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1675
1676         mono_image_add_decl_security (assembly, 
1677                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1678
1679         if (mb->pinfo) {
1680                 MonoDynamicTable *mtable;
1681                 guint32 *mvalues;
1682                 
1683                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1684                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1685                 
1686                 count = 0;
1687                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1688                         if (mono_array_get (mb->pinfo, gpointer, i))
1689                                 count++;
1690                 }
1691                 table->rows += count;
1692                 alloc_table (table, table->rows);
1693                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1694                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1695                         MonoReflectionParamBuilder *pb;
1696                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1697                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1698                                 values [MONO_PARAM_SEQUENCE] = i;
1699                                 if (pb->name != NULL) {
1700                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1701                                 } else {
1702                                         values [MONO_PARAM_NAME] = 0;
1703                                 }
1704                                 values += MONO_PARAM_SIZE;
1705                                 if (pb->marshal_info) {
1706                                         mtable->rows++;
1707                                         alloc_table (mtable, mtable->rows);
1708                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1709                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1710                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1711                                         return_val_if_nok (error, FALSE);
1712                                 }
1713                                 pb->table_idx = table->next_idx++;
1714                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1715                                         guint32 field_type = 0;
1716                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1717                                         mtable->rows ++;
1718                                         alloc_table (mtable, mtable->rows);
1719                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1720                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1721                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1722                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1723                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1724                                 }
1725                         }
1726                 }
1727         }
1728
1729         return TRUE;
1730 }
1731
1732 #ifndef DISABLE_REFLECTION_EMIT
1733 static gboolean
1734 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1735 {
1736         MONO_REQ_GC_UNSAFE_MODE;
1737
1738         mono_error_init (error);
1739         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1740
1741         rmb->ilgen = mb->ilgen;
1742         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1743         return_val_if_nok (error, FALSE);
1744         rmb->parameters = mb->parameters;
1745         rmb->generic_params = mb->generic_params;
1746         rmb->generic_container = mb->generic_container;
1747         rmb->opt_types = NULL;
1748         rmb->pinfo = mb->pinfo;
1749         rmb->attrs = mb->attrs;
1750         rmb->iattrs = mb->iattrs;
1751         rmb->call_conv = mb->call_conv;
1752         rmb->code = mb->code;
1753         rmb->type = mb->type;
1754         rmb->name = mb->name;
1755         rmb->table_idx = &mb->table_idx;
1756         rmb->init_locals = mb->init_locals;
1757         rmb->skip_visibility = FALSE;
1758         rmb->return_modreq = mb->return_modreq;
1759         rmb->return_modopt = mb->return_modopt;
1760         rmb->param_modreq = mb->param_modreq;
1761         rmb->param_modopt = mb->param_modopt;
1762         rmb->permissions = mb->permissions;
1763         rmb->mhandle = mb->mhandle;
1764         rmb->nrefs = 0;
1765         rmb->refs = NULL;
1766
1767         if (mb->dll) {
1768                 rmb->charset = mb->charset;
1769                 rmb->extra_flags = mb->extra_flags;
1770                 rmb->native_cc = mb->native_cc;
1771                 rmb->dllentry = mb->dllentry;
1772                 rmb->dll = mb->dll;
1773         }
1774
1775         return TRUE;
1776 }
1777
1778 static gboolean
1779 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1780 {
1781         MONO_REQ_GC_UNSAFE_MODE;
1782
1783         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1784
1785         mono_error_init (error);
1786
1787         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1788
1789         rmb->ilgen = mb->ilgen;
1790         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1791         return_val_if_nok (error, FALSE);
1792         rmb->parameters = mb->parameters;
1793         rmb->generic_params = NULL;
1794         rmb->generic_container = NULL;
1795         rmb->opt_types = NULL;
1796         rmb->pinfo = mb->pinfo;
1797         rmb->attrs = mb->attrs;
1798         rmb->iattrs = mb->iattrs;
1799         rmb->call_conv = mb->call_conv;
1800         rmb->code = NULL;
1801         rmb->type = mb->type;
1802         rmb->name = mono_string_new (mono_domain_get (), name);
1803         rmb->table_idx = &mb->table_idx;
1804         rmb->init_locals = mb->init_locals;
1805         rmb->skip_visibility = FALSE;
1806         rmb->return_modreq = NULL;
1807         rmb->return_modopt = NULL;
1808         rmb->param_modreq = mb->param_modreq;
1809         rmb->param_modopt = mb->param_modopt;
1810         rmb->permissions = mb->permissions;
1811         rmb->mhandle = mb->mhandle;
1812         rmb->nrefs = 0;
1813         rmb->refs = NULL;
1814
1815         return TRUE;
1816 }
1817
1818 static void
1819 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1820 {
1821         MONO_REQ_GC_UNSAFE_MODE;
1822
1823         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1824
1825         rmb->ilgen = mb->ilgen;
1826         rmb->rtype = mb->rtype;
1827         rmb->parameters = mb->parameters;
1828         rmb->generic_params = NULL;
1829         rmb->generic_container = NULL;
1830         rmb->opt_types = NULL;
1831         rmb->pinfo = NULL;
1832         rmb->attrs = mb->attrs;
1833         rmb->iattrs = 0;
1834         rmb->call_conv = mb->call_conv;
1835         rmb->code = NULL;
1836         rmb->type = (MonoObject *) mb->owner;
1837         rmb->name = mb->name;
1838         rmb->table_idx = NULL;
1839         rmb->init_locals = mb->init_locals;
1840         rmb->skip_visibility = mb->skip_visibility;
1841         rmb->return_modreq = NULL;
1842         rmb->return_modopt = NULL;
1843         rmb->param_modreq = NULL;
1844         rmb->param_modopt = NULL;
1845         rmb->permissions = NULL;
1846         rmb->mhandle = mb->mhandle;
1847         rmb->nrefs = 0;
1848         rmb->refs = NULL;
1849 }       
1850 #endif
1851
1852 static gboolean
1853 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1854 {
1855         MONO_REQ_GC_UNSAFE_MODE;
1856
1857         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1858         MonoDynamicTable *table;
1859         guint32 *values;
1860         guint32 tok;
1861         MonoReflectionMethod *m;
1862         int i;
1863
1864         mono_error_init (error);
1865
1866         if (!mb->override_methods)
1867                 return TRUE;
1868
1869         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1870                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1871
1872                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1873                 table->rows ++;
1874                 alloc_table (table, table->rows);
1875                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1876                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1877                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1878
1879                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1880                 return_val_if_nok (error, FALSE);
1881
1882                 switch (mono_metadata_token_table (tok)) {
1883                 case MONO_TABLE_MEMBERREF:
1884                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1885                         break;
1886                 case MONO_TABLE_METHOD:
1887                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1888                         break;
1889                 default:
1890                         g_assert_not_reached ();
1891                 }
1892                 values [MONO_METHODIMPL_DECLARATION] = tok;
1893         }
1894
1895         return TRUE;
1896 }
1897
1898 #ifndef DISABLE_REFLECTION_EMIT
1899 static gboolean
1900 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1901 {
1902         MONO_REQ_GC_UNSAFE_MODE;
1903
1904         MonoDynamicTable *table;
1905         guint32 *values;
1906         ReflectionMethodBuilder rmb;
1907         int i;
1908
1909         mono_error_init (error);
1910
1911         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1912             !mono_image_basic_method (&rmb, assembly, error))
1913                 return FALSE;
1914
1915         mb->table_idx = *rmb.table_idx;
1916
1917         if (mb->dll) { /* It's a P/Invoke method */
1918                 guint32 moduleref;
1919                 /* map CharSet values to on-disk values */
1920                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1921                 int extra_flags = mb->extra_flags;
1922                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1923                 table->rows ++;
1924                 alloc_table (table, table->rows);
1925                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1926                 
1927                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1928                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1929                 if (mb->dllentry)
1930                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1931                 else
1932                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1933                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1934                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1935                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1936                         table->rows ++;
1937                         alloc_table (table, table->rows);
1938                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1939                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1940                 }
1941         }
1942
1943         if (mb->generic_params) {
1944                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1945                 table->rows += mono_array_length (mb->generic_params);
1946                 alloc_table (table, table->rows);
1947                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1948                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1949
1950                         mono_image_get_generic_param_info (
1951                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1952                 }
1953         }
1954
1955         return TRUE;
1956 }
1957
1958 static gboolean
1959 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1960 {
1961         MONO_REQ_GC_UNSAFE_MODE;
1962
1963         ReflectionMethodBuilder rmb;
1964
1965         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1966                 return FALSE;
1967
1968         if (!mono_image_basic_method (&rmb, assembly, error))
1969                 return FALSE;
1970
1971         mb->table_idx = *rmb.table_idx;
1972
1973         return TRUE;
1974 }
1975 #endif
1976
1977 static char*
1978 type_get_fully_qualified_name (MonoType *type)
1979 {
1980         MONO_REQ_GC_NEUTRAL_MODE;
1981
1982         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1983 }
1984
1985 static char*
1986 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1987 {
1988         MONO_REQ_GC_UNSAFE_MODE;
1989
1990         MonoClass *klass;
1991         MonoAssembly *ta;
1992
1993         klass = mono_class_from_mono_type (type);
1994         if (!klass) 
1995                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1996         ta = klass->image->assembly;
1997         if (assembly_is_dynamic (ta) || (ta == ass)) {
1998                 if (klass->generic_class || klass->generic_container)
1999                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
2000                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2001                 else
2002                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2003         }
2004
2005         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2006 }
2007
2008 #ifndef DISABLE_REFLECTION_EMIT
2009 /*field_image is the image to which the eventual custom mods have been encoded against*/
2010 static guint32
2011 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2012 {
2013         MONO_REQ_GC_NEUTRAL_MODE;
2014
2015         SigBuffer buf;
2016         guint32 idx, i, token;
2017
2018         if (!assembly->save)
2019                 return 0;
2020
2021         sigbuffer_init (&buf, 32);
2022         
2023         sigbuffer_add_value (&buf, 0x06);
2024         /* encode custom attributes before the type */
2025         if (type->num_mods) {
2026                 for (i = 0; i < type->num_mods; ++i) {
2027                         if (field_image) {
2028                                 MonoError error;
2029                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2030                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2031
2032                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2033                         } else {
2034                                 token = type->modifiers [i].token;
2035                         }
2036
2037                         if (type->modifiers [i].required)
2038                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2039                         else
2040                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2041
2042                         sigbuffer_add_value (&buf, token);
2043                 }
2044         }
2045         encode_type (assembly, type, &buf);
2046         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2047         sigbuffer_free (&buf);
2048         return idx;
2049 }
2050 #endif
2051
2052 static guint32
2053 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2054 {
2055         MONO_REQ_GC_UNSAFE_MODE;
2056
2057         mono_error_init (error);
2058
2059         SigBuffer buf;
2060         guint32 idx;
2061         guint32 typespec = 0;
2062         MonoType *type;
2063         MonoClass *klass;
2064
2065         init_type_builder_generics (fb->type);
2066
2067         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2068         return_val_if_nok (error, 0);
2069         klass = mono_class_from_mono_type (type);
2070
2071         sigbuffer_init (&buf, 32);
2072         
2073         sigbuffer_add_value (&buf, 0x06);
2074         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2075         if (!is_ok (error))
2076                 goto fail;
2077         /* encode custom attributes before the type */
2078
2079         if (klass->generic_container)
2080                 typespec = create_typespec (assembly, type);
2081
2082         if (typespec) {
2083                 MonoGenericClass *gclass;
2084                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2085                 encode_generic_class (assembly, gclass, &buf);
2086         } else {
2087                 encode_type (assembly, type, &buf);
2088         }
2089         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2090         sigbuffer_free (&buf);
2091         return idx;
2092 fail:
2093         sigbuffer_free (&buf);
2094         return 0;
2095 }
2096
2097 static guint32
2098 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2099 {
2100         MONO_REQ_GC_UNSAFE_MODE;
2101
2102         char blob_size [64];
2103         char *b = blob_size;
2104         char *box_val;
2105         char* buf;
2106         guint32 idx = 0, len = 0, dummy = 0;
2107
2108         buf = (char *)g_malloc (64);
2109         if (!val) {
2110                 *ret_type = MONO_TYPE_CLASS;
2111                 len = 4;
2112                 box_val = (char*)&dummy;
2113         } else {
2114                 box_val = ((char*)val) + sizeof (MonoObject);
2115                 *ret_type = val->vtable->klass->byval_arg.type;
2116         }
2117 handle_enum:
2118         switch (*ret_type) {
2119         case MONO_TYPE_BOOLEAN:
2120         case MONO_TYPE_U1:
2121         case MONO_TYPE_I1:
2122                 len = 1;
2123                 break;
2124         case MONO_TYPE_CHAR:
2125         case MONO_TYPE_U2:
2126         case MONO_TYPE_I2:
2127                 len = 2;
2128                 break;
2129         case MONO_TYPE_U4:
2130         case MONO_TYPE_I4:
2131         case MONO_TYPE_R4:
2132                 len = 4;
2133                 break;
2134         case MONO_TYPE_U8:
2135         case MONO_TYPE_I8:
2136                 len = 8;
2137                 break;
2138         case MONO_TYPE_R8:
2139                 len = 8;
2140                 break;
2141         case MONO_TYPE_VALUETYPE: {
2142                 MonoClass *klass = val->vtable->klass;
2143                 
2144                 if (klass->enumtype) {
2145                         *ret_type = mono_class_enum_basetype (klass)->type;
2146                         goto handle_enum;
2147                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2148                         len = 8;
2149                 } else 
2150                         g_error ("we can't encode valuetypes, we should have never reached this line");
2151                 break;
2152         }
2153         case MONO_TYPE_CLASS:
2154                 break;
2155         case MONO_TYPE_STRING: {
2156                 MonoString *str = (MonoString*)val;
2157                 /* there is no signature */
2158                 len = str->length * 2;
2159                 mono_metadata_encode_value (len, b, &b);
2160 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2161                 {
2162                         char *swapped = g_malloc (2 * mono_string_length (str));
2163                         const char *p = (const char*)mono_string_chars (str);
2164
2165                         swap_with_size (swapped, p, 2, mono_string_length (str));
2166                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2167                         g_free (swapped);
2168                 }
2169 #else
2170                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2171 #endif
2172
2173                 g_free (buf);
2174                 return idx;
2175         }
2176         case MONO_TYPE_GENERICINST:
2177                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2178                 goto handle_enum;
2179         default:
2180                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2181         }
2182
2183         /* there is no signature */
2184         mono_metadata_encode_value (len, b, &b);
2185 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2186         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2187         swap_with_size (blob_size, box_val, len, 1);
2188         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2189 #else
2190         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2191 #endif
2192
2193         g_free (buf);
2194         return idx;
2195 }
2196
2197 static guint32
2198 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2199 {
2200         MONO_REQ_GC_UNSAFE_MODE;
2201
2202         mono_error_init (error);
2203
2204         char *str;
2205         SigBuffer buf;
2206         guint32 idx, len;
2207
2208         sigbuffer_init (&buf, 32);
2209
2210         sigbuffer_add_value (&buf, minfo->type);
2211
2212         switch (minfo->type) {
2213         case MONO_NATIVE_BYVALTSTR:
2214         case MONO_NATIVE_BYVALARRAY:
2215                 sigbuffer_add_value (&buf, minfo->count);
2216                 break;
2217         case MONO_NATIVE_LPARRAY:
2218                 if (minfo->eltype || minfo->has_size) {
2219                         sigbuffer_add_value (&buf, minfo->eltype);
2220                         if (minfo->has_size) {
2221                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2222                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2223
2224                                 /* LAMESPEC: ElemMult is undocumented */
2225                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2226                         }
2227                 }
2228                 break;
2229         case MONO_NATIVE_SAFEARRAY:
2230                 if (minfo->eltype)
2231                         sigbuffer_add_value (&buf, minfo->eltype);
2232                 break;
2233         case MONO_NATIVE_CUSTOM:
2234                 if (minfo->guid) {
2235                         str = mono_string_to_utf8 (minfo->guid);
2236                         len = strlen (str);
2237                         sigbuffer_add_value (&buf, len);
2238                         sigbuffer_add_mem (&buf, str, len);
2239                         g_free (str);
2240                 } else {
2241                         sigbuffer_add_value (&buf, 0);
2242                 }
2243                 /* native type name */
2244                 sigbuffer_add_value (&buf, 0);
2245                 /* custom marshaler type name */
2246                 if (minfo->marshaltype || minfo->marshaltyperef) {
2247                         if (minfo->marshaltyperef) {
2248                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2249                                 if (!is_ok (error)) {
2250                                         sigbuffer_free (&buf);
2251                                         return 0;
2252                                 }
2253                                 str = type_get_fully_qualified_name (marshaltype);
2254                         } else
2255                                 str = mono_string_to_utf8 (minfo->marshaltype);
2256                         len = strlen (str);
2257                         sigbuffer_add_value (&buf, len);
2258                         sigbuffer_add_mem (&buf, str, len);
2259                         g_free (str);
2260                 } else {
2261                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2262                         sigbuffer_add_value (&buf, 0);
2263                 }
2264                 if (minfo->mcookie) {
2265                         str = mono_string_to_utf8 (minfo->mcookie);
2266                         len = strlen (str);
2267                         sigbuffer_add_value (&buf, len);
2268                         sigbuffer_add_mem (&buf, str, len);
2269                         g_free (str);
2270                 } else {
2271                         sigbuffer_add_value (&buf, 0);
2272                 }
2273                 break;
2274         default:
2275                 break;
2276         }
2277         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2278         sigbuffer_free (&buf);
2279         return idx;
2280 }
2281
2282 static void
2283 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2284 {
2285         MONO_REQ_GC_UNSAFE_MODE;
2286
2287         mono_error_init (error);
2288
2289         MonoDynamicTable *table;
2290         guint32 *values;
2291
2292         /* maybe this fixup should be done in the C# code */
2293         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2294                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2295         table = &assembly->tables [MONO_TABLE_FIELD];
2296         fb->table_idx = table->next_idx ++;
2297         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2298         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2299         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2300         values [MONO_FIELD_FLAGS] = fb->attrs;
2301         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2302         return_if_nok (error);
2303
2304
2305         if (fb->offset != -1) {
2306                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2307                 table->rows ++;
2308                 alloc_table (table, table->rows);
2309                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2310                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2311                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2312         }
2313         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2314                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2315                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2316                 table->rows ++;
2317                 alloc_table (table, table->rows);
2318                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2319                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2320                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2321                 values [MONO_CONSTANT_TYPE] = field_type;
2322                 values [MONO_CONSTANT_PADDING] = 0;
2323         }
2324         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2325                 guint32 rva_idx;
2326                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2327                 table->rows ++;
2328                 alloc_table (table, table->rows);
2329                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2330                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2331                 /*
2332                  * We store it in the code section because it's simpler for now.
2333                  */
2334                 if (fb->rva_data) {
2335                         if (mono_array_length (fb->rva_data) >= 10)
2336                                 stream_data_align (&assembly->code);
2337                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2338                 } else
2339                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2340                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2341         }
2342         if (fb->marshal_info) {
2343                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2344                 table->rows ++;
2345                 alloc_table (table, table->rows);
2346                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2347                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2348                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2349                 return_if_nok (error);
2350         }
2351 }
2352
2353 static guint32
2354 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2355 {
2356         MONO_REQ_GC_UNSAFE_MODE;
2357
2358         mono_error_init (error);
2359
2360         SigBuffer buf;
2361         guint32 nparams = 0;
2362         MonoReflectionMethodBuilder *mb = fb->get_method;
2363         MonoReflectionMethodBuilder *smb = fb->set_method;
2364         guint32 idx, i;
2365
2366         if (mb && mb->parameters)
2367                 nparams = mono_array_length (mb->parameters);
2368         if (!mb && smb && smb->parameters)
2369                 nparams = mono_array_length (smb->parameters) - 1;
2370         sigbuffer_init (&buf, 32);
2371         if (fb->call_conv & 0x20)
2372                 sigbuffer_add_byte (&buf, 0x28);
2373         else
2374                 sigbuffer_add_byte (&buf, 0x08);
2375         sigbuffer_add_value (&buf, nparams);
2376         if (mb) {
2377                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2378                 if (!is_ok (error))
2379                         goto fail;
2380                 for (i = 0; i < nparams; ++i) {
2381                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2382                         encode_reflection_type (assembly, pt, &buf, error);
2383                         if (!is_ok (error))
2384                                 goto fail;
2385                 }
2386         } else if (smb && smb->parameters) {
2387                 /* the property type is the last param */
2388                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2389                 if (!is_ok (error))
2390                         goto fail;
2391
2392                 for (i = 0; i < nparams; ++i) {
2393                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2394                         encode_reflection_type (assembly, pt, &buf, error);
2395                         if (!is_ok (error))
2396                                 goto fail;
2397                 }
2398         } else {
2399                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2400                 if (!is_ok (error))
2401                         goto fail;
2402         }
2403
2404         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2405         sigbuffer_free (&buf);
2406         return idx;
2407 fail:
2408         sigbuffer_free (&buf);
2409         return 0;
2410 }
2411
2412 static void
2413 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2414 {
2415         MONO_REQ_GC_UNSAFE_MODE;
2416
2417         mono_error_init (error);
2418
2419         MonoDynamicTable *table;
2420         guint32 *values;
2421         guint num_methods = 0;
2422         guint32 semaidx;
2423
2424         /* 
2425          * we need to set things in the following tables:
2426          * PROPERTYMAP (info already filled in _get_type_info ())
2427          * PROPERTY    (rows already preallocated in _get_type_info ())
2428          * METHOD      (method info already done with the generic method code)
2429          * METHODSEMANTICS
2430          * CONSTANT
2431          */
2432         table = &assembly->tables [MONO_TABLE_PROPERTY];
2433         pb->table_idx = table->next_idx ++;
2434         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2435         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2436         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2437         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2438         return_if_nok (error);
2439
2440
2441         /* FIXME: we still don't handle 'other' methods */
2442         if (pb->get_method) num_methods ++;
2443         if (pb->set_method) num_methods ++;
2444
2445         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2446         table->rows += num_methods;
2447         alloc_table (table, table->rows);
2448
2449         if (pb->get_method) {
2450                 semaidx = table->next_idx ++;
2451                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2452                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2453                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2454                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2455         }
2456         if (pb->set_method) {
2457                 semaidx = table->next_idx ++;
2458                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2459                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2460                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2461                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2462         }
2463         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2464                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2465                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2466                 table->rows ++;
2467                 alloc_table (table, table->rows);
2468                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2469                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2470                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2471                 values [MONO_CONSTANT_TYPE] = field_type;
2472                 values [MONO_CONSTANT_PADDING] = 0;
2473         }
2474 }
2475
2476 static void
2477 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2478 {
2479         MONO_REQ_GC_UNSAFE_MODE;
2480
2481         MonoDynamicTable *table;
2482         guint32 *values;
2483         guint num_methods = 0;
2484         guint32 semaidx;
2485
2486         /* 
2487          * we need to set things in the following tables:
2488          * EVENTMAP (info already filled in _get_type_info ())
2489          * EVENT    (rows already preallocated in _get_type_info ())
2490          * METHOD      (method info already done with the generic method code)
2491          * METHODSEMANTICS
2492          */
2493         table = &assembly->tables [MONO_TABLE_EVENT];
2494         eb->table_idx = table->next_idx ++;
2495         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2496         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2497         values [MONO_EVENT_FLAGS] = eb->attrs;
2498         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2499         return_if_nok (error);
2500         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2501
2502         /*
2503          * FIXME: we still don't handle 'other' methods 
2504          */
2505         if (eb->add_method) num_methods ++;
2506         if (eb->remove_method) num_methods ++;
2507         if (eb->raise_method) num_methods ++;
2508
2509         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2510         table->rows += num_methods;
2511         alloc_table (table, table->rows);
2512
2513         if (eb->add_method) {
2514                 semaidx = table->next_idx ++;
2515                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2516                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2517                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2518                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2519         }
2520         if (eb->remove_method) {
2521                 semaidx = table->next_idx ++;
2522                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2523                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2524                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2525                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2526         }
2527         if (eb->raise_method) {
2528                 semaidx = table->next_idx ++;
2529                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2530                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2531                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2532                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2533         }
2534 }
2535
2536 static void
2537 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2538 {
2539         MONO_REQ_GC_UNSAFE_MODE;
2540
2541         mono_error_init (error);
2542
2543         MonoDynamicTable *table;
2544         guint32 num_constraints, i;
2545         guint32 *values;
2546         guint32 table_idx;
2547
2548         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2549         num_constraints = gparam->iface_constraints ?
2550                 mono_array_length (gparam->iface_constraints) : 0;
2551         table->rows += num_constraints;
2552         if (gparam->base_type)
2553                 table->rows++;
2554         alloc_table (table, table->rows);
2555
2556         if (gparam->base_type) {
2557                 table_idx = table->next_idx ++;
2558                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2559
2560                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2561                 return_if_nok (error);
2562                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2563                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2564         }
2565
2566         for (i = 0; i < num_constraints; i++) {
2567                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2568                         gparam->iface_constraints, gpointer, i);
2569
2570                 table_idx = table->next_idx ++;
2571                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2572
2573                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2574                 return_if_nok (error);
2575
2576                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2577                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2578         }
2579 }
2580
2581 static void
2582 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2583 {
2584         MONO_REQ_GC_UNSAFE_MODE;
2585
2586         GenericParamTableEntry *entry;
2587
2588         /*
2589          * The GenericParam table must be sorted according to the `owner' field.
2590          * We need to do this sorting prior to writing the GenericParamConstraint
2591          * table, since we have to use the final GenericParam table indices there
2592          * and they must also be sorted.
2593          */
2594
2595         entry = g_new0 (GenericParamTableEntry, 1);
2596         entry->owner = owner;
2597         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2598         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2599         entry->gparam = gparam;
2600         
2601         g_ptr_array_add (assembly->gen_params, entry);
2602 }
2603
2604 static gboolean
2605 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2606 {
2607         MONO_REQ_GC_UNSAFE_MODE;
2608
2609         MonoDynamicTable *table;
2610         MonoGenericParam *param;
2611         guint32 *values;
2612         guint32 table_idx;
2613
2614         mono_error_init (error);
2615
2616         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2617         table_idx = table->next_idx ++;
2618         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2619
2620         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2621         return_val_if_nok (error, FALSE);
2622
2623         param = gparam_type->data.generic_param;
2624
2625         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2626         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2627         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2628         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2629
2630         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2631                 return FALSE;
2632
2633         encode_constraints (entry->gparam, table_idx, assembly, error);
2634         return_val_if_nok (error, FALSE);
2635
2636         return TRUE;
2637 }
2638
2639 static guint32
2640 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2641 {
2642         MONO_REQ_GC_UNSAFE_MODE;
2643
2644         MonoDynamicTable *table;
2645         guint32 token;
2646         guint32 *values;
2647         guint32 cols [MONO_ASSEMBLY_SIZE];
2648         const char *pubkey;
2649         guint32 publen;
2650
2651         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2652                 return token;
2653
2654         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2655                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2656                 token = table->next_idx ++;
2657                 table->rows ++;
2658                 alloc_table (table, table->rows);
2659                 values = table->values + token * MONO_MODULEREF_SIZE;
2660                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2661
2662                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2663                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2664                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2665
2666                 return token;
2667         }
2668         
2669         if (assembly_is_dynamic (image->assembly))
2670                 /* FIXME: */
2671                 memset (cols, 0, sizeof (cols));
2672         else {
2673                 /* image->assembly->image is the manifest module */
2674                 image = image->assembly->image;
2675                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2676         }
2677
2678         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2679         token = table->next_idx ++;
2680         table->rows ++;
2681         alloc_table (table, table->rows);
2682         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2683         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2684         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2685         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2686         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2687         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2688         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2689         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2690         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2691
2692         if (strcmp ("", image->assembly->aname.culture)) {
2693                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2694                                 image->assembly->aname.culture);
2695         }
2696
2697         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2698                 guchar pubtoken [9];
2699                 pubtoken [0] = 8;
2700                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2701                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2702         } else {
2703                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2704         }
2705         token <<= MONO_RESOLUTION_SCOPE_BITS;
2706         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2707         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2708         return token;
2709 }
2710
2711 static guint32
2712 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2713 {
2714         MONO_REQ_GC_NEUTRAL_MODE;
2715
2716         MonoDynamicTable *table;
2717         guint32 *values;
2718         guint32 token;
2719         SigBuffer buf;
2720
2721         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2722                 return token;
2723
2724         sigbuffer_init (&buf, 32);
2725         switch (type->type) {
2726         case MONO_TYPE_FNPTR:
2727         case MONO_TYPE_PTR:
2728         case MONO_TYPE_SZARRAY:
2729         case MONO_TYPE_ARRAY:
2730         case MONO_TYPE_VAR:
2731         case MONO_TYPE_MVAR:
2732         case MONO_TYPE_GENERICINST:
2733                 encode_type (assembly, type, &buf);
2734                 break;
2735         case MONO_TYPE_CLASS:
2736         case MONO_TYPE_VALUETYPE: {
2737                 MonoClass *k = mono_class_from_mono_type (type);
2738                 if (!k || !k->generic_container) {
2739                         sigbuffer_free (&buf);
2740                         return 0;
2741                 }
2742                 encode_type (assembly, type, &buf);
2743                 break;
2744         }
2745         default:
2746                 sigbuffer_free (&buf);
2747                 return 0;
2748         }
2749
2750         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2751         if (assembly->save) {
2752                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2753                 alloc_table (table, table->rows + 1);
2754                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2755                 values [MONO_TYPESPEC_SIGNATURE] = token;
2756         }
2757         sigbuffer_free (&buf);
2758
2759         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2760         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2761         table->next_idx ++;
2762         return token;
2763 }
2764
2765 static guint32
2766 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2767 {
2768         MONO_REQ_GC_UNSAFE_MODE;
2769
2770         MonoDynamicTable *table;
2771         guint32 *values;
2772         guint32 token, scope, enclosing;
2773         MonoClass *klass;
2774
2775         /* if the type requires a typespec, we must try that first*/
2776         if (try_typespec && (token = create_typespec (assembly, type)))
2777                 return token;
2778         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2779         if (token)
2780                 return token;
2781         klass = mono_class_from_mono_type (type);
2782         if (!klass)
2783                 klass = mono_class_from_mono_type (type);
2784
2785         /*
2786          * If it's in the same module and not a generic type parameter:
2787          */
2788         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2789                         (type->type != MONO_TYPE_MVAR)) {
2790                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2791                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2792                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2793                 return token;
2794         }
2795
2796         if (klass->nested_in) {
2797                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2798                 /* get the typeref idx of the enclosing type */
2799                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2800                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2801         } else {
2802                 scope = resolution_scope_from_image (assembly, klass->image);
2803         }
2804         table = &assembly->tables [MONO_TABLE_TYPEREF];
2805         if (assembly->save) {
2806                 alloc_table (table, table->rows + 1);
2807                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2808                 values [MONO_TYPEREF_SCOPE] = scope;
2809                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2810                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2811         }
2812         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2813         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2814         table->next_idx ++;
2815         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2816         return token;
2817 }
2818
2819 /*
2820  * Despite the name, we handle also TypeSpec (with the above helper).
2821  */
2822 static guint32
2823 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2824 {
2825         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2826 }
2827
2828 #ifndef DISABLE_REFLECTION_EMIT
2829 static guint32
2830 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2831 {
2832         MONO_REQ_GC_NEUTRAL_MODE;
2833
2834         MonoDynamicTable *table;
2835         guint32 *values;
2836         guint32 token, pclass;
2837
2838         switch (parent & MONO_TYPEDEFORREF_MASK) {
2839         case MONO_TYPEDEFORREF_TYPEREF:
2840                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2841                 break;
2842         case MONO_TYPEDEFORREF_TYPESPEC:
2843                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2844                 break;
2845         case MONO_TYPEDEFORREF_TYPEDEF:
2846                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2847                 break;
2848         default:
2849                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2850                 return 0;
2851         }
2852         /* extract the index */
2853         parent >>= MONO_TYPEDEFORREF_BITS;
2854
2855         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2856
2857         if (assembly->save) {
2858                 alloc_table (table, table->rows + 1);
2859                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2860                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2861                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2862                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2863         }
2864
2865         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2866         table->next_idx ++;
2867
2868         return token;
2869 }
2870
2871 /*
2872  * Insert a memberef row into the metadata: the token that point to the memberref
2873  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2874  * mono_image_get_fieldref_token()).
2875  * The sig param is an index to an already built signature.
2876  */
2877 static guint32
2878 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2879 {
2880         MONO_REQ_GC_NEUTRAL_MODE;
2881
2882         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2883         return mono_image_add_memberef_row (assembly, parent, name, sig);
2884 }
2885
2886
2887 static guint32
2888 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2889 {
2890         MONO_REQ_GC_NEUTRAL_MODE;
2891
2892         guint32 token;
2893         MonoMethodSignature *sig;
2894         
2895         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2896
2897         if (create_typespec) {
2898                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2899                 if (token)
2900                         return token;
2901         } 
2902
2903         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2904         if (token && !create_typespec)
2905                 return token;
2906
2907         g_assert (!method->is_inflated);
2908         if (!token) {
2909                 /*
2910                  * A methodref signature can't contain an unmanaged calling convention.
2911                  */
2912                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2913                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2914                         sig->call_convention = MONO_CALL_DEFAULT;
2915                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2916                         method->name,  method_encode_signature (assembly, sig));
2917                 g_free (sig);
2918                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2919         }
2920
2921         if (create_typespec) {
2922                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2923                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2924                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2925
2926                 if (assembly->save) {
2927                         guint32 *values;
2928
2929                         alloc_table (table, table->rows + 1);
2930                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2931                         values [MONO_METHODSPEC_METHOD] = token;
2932                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2933                 }
2934
2935                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2936                 table->next_idx ++;
2937                 /*methodspec and memberef tokens are diferent, */
2938                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2939                 return token;
2940         }
2941         return token;
2942 }
2943
2944 static guint32
2945 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2946 {
2947         guint32 token, parent, sig;
2948         ReflectionMethodBuilder rmb;
2949         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2950         
2951         mono_error_init (error);
2952         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2953         if (token)
2954                 return token;
2955
2956         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2957                 return 0;
2958
2959         /*
2960          * A methodref signature can't contain an unmanaged calling convention.
2961          * Since some flags are encoded as part of call_conv, we need to check against it.
2962         */
2963         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2964                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2965
2966         sig = method_builder_encode_signature (assembly, &rmb, error);
2967         return_val_if_nok (error, 0);
2968
2969         if (tb->generic_params) {
2970                 parent = create_generic_typespec (assembly, tb, error);
2971                 return_val_if_nok (error, 0);
2972         } else {
2973                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2974                 return_val_if_nok (error, 0);
2975
2976                 parent = mono_image_typedef_or_ref (assembly, t);
2977         }
2978
2979         char *name = mono_string_to_utf8 (method->name);
2980
2981         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2982         g_free (name);
2983
2984         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2985
2986         return token;
2987 }
2988
2989 static guint32
2990 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2991                                      const gchar *name, guint32 sig)
2992 {
2993         MonoDynamicTable *table;
2994         guint32 token;
2995         guint32 *values;
2996         
2997         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2998
2999         if (assembly->save) {
3000                 alloc_table (table, table->rows + 1);
3001                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3002                 values [MONO_MEMBERREF_CLASS] = original;
3003                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3004                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3005         }
3006
3007         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3008         table->next_idx ++;
3009
3010         return token;
3011 }
3012
3013 static guint32
3014 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3015 {
3016         SigBuffer buf;
3017         int i;
3018         guint32 nparams = mono_array_length (mb->generic_params);
3019         guint32 idx;
3020
3021         if (!assembly->save)
3022                 return 0;
3023
3024         sigbuffer_init (&buf, 32);
3025
3026         sigbuffer_add_value (&buf, 0xa);
3027         sigbuffer_add_value (&buf, nparams);
3028
3029         for (i = 0; i < nparams; i++) {
3030                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3031                 sigbuffer_add_value (&buf, i);
3032         }
3033
3034         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3035         sigbuffer_free (&buf);
3036         return idx;
3037 }
3038
3039 static guint32
3040 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3041 {
3042         MonoDynamicTable *table;
3043         guint32 *values;
3044         guint32 token, mtoken = 0;
3045
3046         mono_error_init (error);
3047         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3048         if (token)
3049                 return token;
3050
3051         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3052
3053         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3054         if (!mono_error_ok (error))
3055                 return 0;
3056
3057         switch (mono_metadata_token_table (mtoken)) {
3058         case MONO_TABLE_MEMBERREF:
3059                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3060                 break;
3061         case MONO_TABLE_METHOD:
3062                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3063                 break;
3064         default:
3065                 g_assert_not_reached ();
3066         }
3067
3068         if (assembly->save) {
3069                 alloc_table (table, table->rows + 1);
3070                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3071                 values [MONO_METHODSPEC_METHOD] = mtoken;
3072                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3073         }
3074
3075         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3076         table->next_idx ++;
3077
3078         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3079         return token;
3080 }
3081
3082 static guint32
3083 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3084 {
3085         guint32 token;
3086
3087         mono_error_init (error);
3088
3089         if (mb->generic_params && create_methodspec) 
3090                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3091
3092         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3093         if (token)
3094                 return token;
3095
3096         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3097         if (!mono_error_ok (error))
3098                 return 0;
3099         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3100         return token;
3101 }
3102
3103 static guint32
3104 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3105 {
3106         guint32 token, parent, sig;
3107         ReflectionMethodBuilder rmb;
3108         char *name;
3109         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3110         
3111         mono_error_init (error);
3112         
3113         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3114         if (token)
3115                 return token;
3116
3117         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3118                 return 0;
3119
3120         if (tb->generic_params) {
3121                 parent = create_generic_typespec (assembly, tb, error);
3122                 return_val_if_nok (error, 0);
3123         } else {
3124                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3125                 return_val_if_nok (error, 0);
3126                 parent = mono_image_typedef_or_ref (assembly, type);
3127         }
3128         
3129         name = mono_string_to_utf8 (rmb.name);
3130         sig = method_builder_encode_signature (assembly, &rmb, error);
3131         return_val_if_nok (error, 0);
3132
3133         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3134
3135         g_free (name);
3136         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3137         return token;
3138 }
3139 #endif
3140
3141 static gboolean
3142 is_field_on_inst (MonoClassField *field)
3143 {
3144         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3145 }
3146
3147 /*
3148  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3149  */
3150 static MonoType*
3151 get_field_on_inst_generic_type (MonoClassField *field)
3152 {
3153         MonoClass *klass, *gtd;
3154         MonoDynamicGenericClass *dgclass;
3155         int field_index;
3156
3157         g_assert (is_field_on_inst (field));
3158
3159         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3160
3161         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3162                 field_index = field - dgclass->fields;
3163                 return dgclass->field_generic_types [field_index];              
3164         }
3165
3166         klass = field->parent;
3167         gtd = klass->generic_class->container_class;
3168
3169         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3170                 field_index = field - klass->fields;
3171                 return gtd->fields [field_index].type;
3172         }
3173
3174         g_assert_not_reached ();
3175         return 0;
3176 }
3177
3178 #ifndef DISABLE_REFLECTION_EMIT
3179 static guint32
3180 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3181 {
3182         MonoType *type;
3183         guint32 token;
3184
3185         g_assert (field);
3186         g_assert (field->parent);
3187
3188         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3189         if (token)
3190                 return token;
3191
3192         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3193                 int index = field - field->parent->fields;
3194                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3195         } else {
3196                 if (is_field_on_inst (field))
3197                         type = get_field_on_inst_generic_type (field);
3198                 else
3199                         type = mono_field_get_type (field);
3200         }
3201         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3202                                                                                         mono_field_get_name (field),
3203                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3204         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3205         return token;
3206 }
3207
3208 static guint32
3209 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3210 {
3211         guint32 token;
3212         MonoClass *klass;
3213         MonoGenericClass *gclass;
3214         MonoType *type;
3215         char *name;
3216
3217         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3218         if (token)
3219                 return token;
3220         if (is_sre_field_builder (mono_object_class (f->fb))) {
3221                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3222                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3223                 return_val_if_nok (error, 0);
3224                 klass = mono_class_from_mono_type (type);
3225                 gclass = type->data.generic_class;
3226                 g_assert (gclass->is_dynamic);
3227
3228                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3229                 return_val_if_nok (error, 0);
3230                 name = mono_string_to_utf8 (fb->name);
3231                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3232                 g_free (name);          
3233         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3234                 guint32 sig;
3235                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3236
3237                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3238                 return_val_if_nok (error, 0);
3239                 klass = mono_class_from_mono_type (type);
3240
3241                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3242                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3243         } else {
3244                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3245                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3246         }
3247
3248         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3249         return token;
3250 }
3251
3252 static guint32
3253 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3254 {
3255         guint32 sig, token;
3256         MonoClass *klass;
3257         MonoGenericClass *gclass;
3258         MonoType *type;
3259
3260         mono_error_init (error);
3261
3262         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3263
3264         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3265         if (token)
3266                 return token;
3267
3268         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3269                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3270                 ReflectionMethodBuilder rmb;
3271                 char *name;
3272
3273                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3274                 return_val_if_nok (error, 0);
3275                 klass = mono_class_from_mono_type (type);
3276
3277                 gclass = type->data.generic_class;
3278                 g_assert (gclass->is_dynamic);
3279
3280                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3281                         return 0;
3282
3283                 sig = method_builder_encode_signature (assembly, &rmb, error);
3284                 return_val_if_nok (error, 0);
3285
3286                 name = mono_string_to_utf8 (rmb.name);
3287
3288                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3289                 g_free (name);
3290         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3291                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3292
3293                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3294                 return_val_if_nok (error, 0);
3295                 klass = mono_class_from_mono_type (type);
3296
3297                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3298                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3299         } else {
3300                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3301                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3302         }
3303
3304
3305         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3306         return token;
3307 }
3308
3309 static MonoMethod*
3310 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3311 {
3312         MonoClass *klass;
3313         MonoGenericContext tmp_context;
3314         MonoType **type_argv;
3315         MonoGenericInst *ginst;
3316         MonoMethod *method, *inflated;
3317         int count, i;
3318
3319         mono_error_init (error);
3320
3321         init_type_builder_generics ((MonoObject*)m->inst);
3322
3323         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3324         return_val_if_nok (error, NULL);
3325
3326         klass = method->klass;
3327
3328         if (m->method_args == NULL)
3329                 return method;
3330
3331         if (method->is_inflated)
3332                 method = ((MonoMethodInflated *) method)->declaring;
3333
3334         count = mono_array_length (m->method_args);
3335
3336         type_argv = g_new0 (MonoType *, count);
3337         for (i = 0; i < count; i++) {
3338                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3339                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3340                 return_val_if_nok (error, NULL);
3341         }
3342         ginst = mono_metadata_get_generic_inst (count, type_argv);
3343         g_free (type_argv);
3344
3345         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3346         tmp_context.method_inst = ginst;
3347
3348         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3349         mono_error_assert_ok (error);
3350         return inflated;
3351 }
3352
3353 static guint32
3354 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3355 {
3356         guint32 sig, token = 0;
3357         MonoType *type;
3358         MonoClass *klass;
3359
3360         mono_error_init (error);
3361
3362         if (m->method_args) {
3363                 MonoMethod *inflated;
3364
3365                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3366                 return_val_if_nok (error, 0);
3367
3368                 if (create_methodspec)
3369                         token = mono_image_get_methodspec_token (assembly, inflated);
3370                 else
3371                         token = mono_image_get_inflated_method_token (assembly, inflated);
3372                 return token;
3373         }
3374
3375         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3376         if (token)
3377                 return token;
3378
3379         if (is_sre_method_builder (mono_object_class (m->mb))) {
3380                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3381                 MonoGenericClass *gclass;
3382                 ReflectionMethodBuilder rmb;
3383                 char *name;
3384
3385                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3386                 return_val_if_nok (error, 0);
3387                 klass = mono_class_from_mono_type (type);
3388                 gclass = type->data.generic_class;
3389                 g_assert (gclass->is_dynamic);
3390
3391                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3392                         return 0;
3393
3394                 sig = method_builder_encode_signature (assembly, &rmb, error);
3395                 return_val_if_nok (error, 0);
3396
3397                 name = mono_string_to_utf8 (rmb.name);
3398
3399                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3400                 g_free (name);          
3401         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3402                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3403
3404                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3405                 return_val_if_nok (error, 0);
3406                 klass = mono_class_from_mono_type (type);
3407
3408                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3409                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3410         } else {
3411                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3412                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3413         }
3414
3415         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3416         return token;
3417 }
3418
3419 static guint32
3420 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3421 {
3422         SigBuffer buf;
3423         int i;
3424         guint32 nparams = context->method_inst->type_argc;
3425         guint32 idx;
3426
3427         if (!assembly->save)
3428                 return 0;
3429
3430         sigbuffer_init (&buf, 32);
3431         /*
3432          * FIXME: vararg, explicit_this, differenc call_conv values...
3433          */
3434         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3435         sigbuffer_add_value (&buf, nparams);
3436
3437         for (i = 0; i < nparams; i++)
3438                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3439
3440         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3441         sigbuffer_free (&buf);
3442         return idx;
3443 }
3444
3445 static guint32
3446 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3447 {
3448         MonoDynamicTable *table;
3449         guint32 *values;
3450         guint32 token, mtoken = 0, sig;
3451         MonoMethodInflated *imethod;
3452         MonoMethod *declaring;
3453
3454         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3455
3456         g_assert (method->is_inflated);
3457         imethod = (MonoMethodInflated *) method;
3458         declaring = imethod->declaring;
3459
3460         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3461         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3462
3463         if (!mono_method_signature (declaring)->generic_param_count)
3464                 return mtoken;
3465
3466         switch (mono_metadata_token_table (mtoken)) {
3467         case MONO_TABLE_MEMBERREF:
3468                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3469                 break;
3470         case MONO_TABLE_METHOD:
3471                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3472                 break;
3473         default:
3474                 g_assert_not_reached ();
3475         }
3476
3477         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3478
3479         if (assembly->save) {
3480                 alloc_table (table, table->rows + 1);
3481                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3482                 values [MONO_METHODSPEC_METHOD] = mtoken;
3483                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3484         }
3485
3486         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3487         table->next_idx ++;
3488
3489         return token;
3490 }
3491
3492 static guint32
3493 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3494 {
3495         MonoMethodInflated *imethod;
3496         guint32 token;
3497         
3498         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3499         if (token)
3500                 return token;
3501
3502         g_assert (method->is_inflated);
3503         imethod = (MonoMethodInflated *) method;
3504
3505         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3506                 token = method_encode_methodspec (assembly, method);
3507         } else {
3508                 guint32 sig = method_encode_signature (
3509                         assembly, mono_method_signature (imethod->declaring));
3510                 token = mono_image_get_memberref_token (
3511                         assembly, &method->klass->byval_arg, method->name, sig);
3512         }
3513
3514         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3515         return token;
3516 }
3517
3518 static guint32
3519 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3520 {
3521         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3522         guint32 sig, token;
3523
3524         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3525         token = mono_image_get_memberref_token (
3526                 assembly, &m->klass->byval_arg, m->name, sig);
3527
3528         return token;
3529 }
3530
3531 static guint32
3532 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3533 {
3534         MonoDynamicTable *table;
3535         MonoClass *klass;
3536         MonoType *type;
3537         guint32 *values;
3538         guint32 token;
3539         SigBuffer buf;
3540         int count, i;
3541
3542         /*
3543          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3544          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3545          * Because of this, we must not insert it into the `typeref' hash table.
3546          */
3547         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3548         return_val_if_nok (error, 0);
3549         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3550         if (token)
3551                 return token;
3552
3553         sigbuffer_init (&buf, 32);
3554
3555         g_assert (tb->generic_params);
3556         klass = mono_class_from_mono_type (type);
3557
3558         if (tb->generic_container)
3559                 mono_reflection_create_generic_class (tb);
3560
3561         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3562         g_assert (klass->generic_container);
3563         sigbuffer_add_value (&buf, klass->byval_arg.type);
3564         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3565
3566         count = mono_array_length (tb->generic_params);
3567         sigbuffer_add_value (&buf, count);
3568         for (i = 0; i < count; i++) {
3569                 MonoReflectionGenericParam *gparam;
3570
3571                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3572                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3573                 if (!is_ok (error))
3574                         goto fail;
3575
3576                 encode_type (assembly, gparam_type, &buf);
3577         }
3578
3579         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3580
3581         if (assembly->save) {
3582                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3583                 alloc_table (table, table->rows + 1);
3584                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3585                 values [MONO_TYPESPEC_SIGNATURE] = token;
3586         }
3587         sigbuffer_free (&buf);
3588
3589         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3590         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3591         table->next_idx ++;
3592         return token;
3593 fail:
3594         sigbuffer_free (&buf);
3595         return 0;
3596 }
3597
3598 /*
3599  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3600  */
3601 static MonoType*
3602 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3603 {
3604         int i, count, len, pos;
3605         MonoType *t;
3606
3607         mono_error_init (error);
3608
3609         count = 0;
3610         if (modreq)
3611                 count += mono_array_length (modreq);
3612         if (modopt)
3613                 count += mono_array_length (modopt);
3614
3615         if (count == 0)
3616                 return mono_metadata_type_dup (NULL, type);
3617
3618         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3619         t = (MonoType *)g_malloc (len);
3620         memcpy (t, type, MONO_SIZEOF_TYPE);
3621
3622         t->num_mods = count;
3623         pos = 0;
3624         if (modreq) {
3625                 for (i = 0; i < mono_array_length (modreq); ++i) {
3626                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3627                         if (!is_ok (error))
3628                                 goto fail;
3629                         t->modifiers [pos].required = 1;
3630                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3631                         pos ++;
3632                 }
3633         }
3634         if (modopt) {
3635                 for (i = 0; i < mono_array_length (modopt); ++i) {
3636                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3637                         if (!is_ok (error))
3638                                 goto fail;
3639                         t->modifiers [pos].required = 0;
3640                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3641                         pos ++;
3642                 }
3643         }
3644
3645         return t;
3646 fail:
3647         g_free (t);
3648         return NULL;
3649 }
3650
3651 static void
3652 init_type_builder_generics (MonoObject *type)
3653 {
3654         MonoReflectionTypeBuilder *tb;
3655
3656         if (!is_sre_type_builder(mono_object_class (type)))
3657                 return;
3658         tb = (MonoReflectionTypeBuilder *)type;
3659
3660         if (tb && tb->generic_container)
3661                 mono_reflection_create_generic_class (tb);
3662 }
3663
3664 static guint32
3665 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3666 {
3667         MonoDynamicTable *table;
3668         MonoType *custom = NULL, *type;
3669         guint32 *values;
3670         guint32 token, pclass, parent, sig;
3671         gchar *name;
3672
3673         mono_error_init (error);
3674
3675         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3676         if (token)
3677                 return token;
3678
3679         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3680         return_val_if_nok (error, 0);
3681         /* FIXME: is this call necessary? */
3682         mono_class_from_mono_type (typeb);
3683
3684         /*FIXME this is one more layer of ugliness due how types are created.*/
3685         init_type_builder_generics (fb->type);
3686
3687         /* fb->type does not include the custom modifiers */
3688         /* FIXME: We should do this in one place when a fieldbuilder is created */
3689         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3690         return_val_if_nok (error, 0);
3691
3692         if (fb->modreq || fb->modopt) {
3693                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3694                 return_val_if_nok (error, 0);
3695         }
3696
3697         sig = fieldref_encode_signature (assembly, NULL, type);
3698         g_free (custom);
3699
3700         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3701         return_val_if_nok (error, 0);
3702         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3703         
3704         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3705         parent >>= MONO_TYPEDEFORREF_BITS;
3706
3707         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3708
3709         name = mono_string_to_utf8 (fb->name);
3710
3711         if (assembly->save) {
3712                 alloc_table (table, table->rows + 1);
3713                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3714                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3715                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3716                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3717         }
3718
3719         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3720         table->next_idx ++;
3721         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3722         g_free (name);
3723         return token;
3724 }
3725
3726 static guint32
3727 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3728 {
3729         SigBuffer buf;
3730         guint32 nargs;
3731         guint32 i, idx;
3732
3733         mono_error_init (error);
3734
3735         if (!assembly->save)
3736                 return 0;
3737
3738         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3739         g_assert (helper->type == 2);
3740
3741         if (helper->arguments)
3742                 nargs = mono_array_length (helper->arguments);
3743         else
3744                 nargs = 0;
3745
3746         sigbuffer_init (&buf, 32);
3747
3748         /* Encode calling convention */
3749         /* Change Any to Standard */
3750         if ((helper->call_conv & 0x03) == 0x03)
3751                 helper->call_conv = 0x01;
3752         /* explicit_this implies has_this */
3753         if (helper->call_conv & 0x40)
3754                 helper->call_conv &= 0x20;
3755
3756         if (helper->call_conv == 0) { /* Unmanaged */
3757                 idx = helper->unmanaged_call_conv - 1;
3758         } else {
3759                 /* Managed */
3760                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3761                 if (helper->call_conv & 0x02) /* varargs */
3762                         idx += 0x05;
3763         }
3764
3765         sigbuffer_add_byte (&buf, idx);
3766         sigbuffer_add_value (&buf, nargs);
3767         encode_reflection_type (assembly, helper->return_type, &buf, error);
3768         if (!is_ok (error))
3769                 goto fail;
3770         for (i = 0; i < nargs; ++i) {
3771                 MonoArray *modreqs = NULL;
3772                 MonoArray *modopts = NULL;
3773                 MonoReflectionType *pt;
3774
3775                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3776                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3777                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3778                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3779
3780                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3781                 if (!is_ok (error))
3782                         goto fail;
3783                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3784                 encode_reflection_type (assembly, pt, &buf, error);
3785                 if (!is_ok (error))
3786                         goto fail;
3787         }
3788         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3789         sigbuffer_free (&buf);
3790
3791         return idx;
3792 fail:
3793         sigbuffer_free (&buf);
3794         return 0;
3795 }
3796
3797 static guint32 
3798 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3799 {
3800         guint32 idx;
3801         MonoDynamicTable *table;
3802         guint32 *values;
3803
3804         mono_error_init (error);
3805
3806         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3807         idx = table->next_idx ++;
3808         table->rows ++;
3809         alloc_table (table, table->rows);
3810         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3811
3812         values [MONO_STAND_ALONE_SIGNATURE] =
3813                 mono_reflection_encode_sighelper (assembly, helper, error);
3814         return_val_if_nok (error, 0);
3815         
3816         return idx;
3817 }
3818
3819 static int
3820 reflection_cc_to_file (int call_conv) {
3821         switch (call_conv & 0x3) {
3822         case 0:
3823         case 1: return MONO_CALL_DEFAULT;
3824         case 2: return MONO_CALL_VARARG;
3825         default:
3826                 g_assert_not_reached ();
3827         }
3828         return 0;
3829 }
3830 #endif /* !DISABLE_REFLECTION_EMIT */
3831
3832 typedef struct {
3833         MonoType *parent;
3834         MonoMethodSignature *sig;
3835         char *name;
3836         guint32 token;
3837 } ArrayMethod;
3838
3839 #ifndef DISABLE_REFLECTION_EMIT
3840 static guint32
3841 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3842 {
3843         guint32 nparams, i;
3844         GList *tmp;
3845         char *name = NULL;
3846         MonoMethodSignature *sig;
3847         ArrayMethod *am = NULL;
3848         MonoType *mtype;
3849
3850         mono_error_init (error);
3851
3852         nparams = mono_array_length (m->parameters);
3853         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3854         sig->hasthis = 1;
3855         sig->sentinelpos = -1;
3856         sig->call_convention = reflection_cc_to_file (m->call_conv);
3857         sig->param_count = nparams;
3858         if (m->ret) {
3859                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3860                 if (!is_ok (error))
3861                         goto fail;
3862         } else
3863                 sig->ret = &mono_defaults.void_class->byval_arg;
3864
3865         mtype = mono_reflection_type_get_handle (m->parent, error);
3866         if (!is_ok (error))
3867                 goto fail;
3868
3869         for (i = 0; i < nparams; ++i) {
3870                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3871                 if (!is_ok (error))
3872                         goto fail;
3873         }
3874
3875         name = mono_string_to_utf8 (m->name);
3876         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3877                 am = (ArrayMethod *)tmp->data;
3878                 if (strcmp (name, am->name) == 0 && 
3879                                 mono_metadata_type_equal (am->parent, mtype) &&
3880                                 mono_metadata_signature_equal (am->sig, sig)) {
3881                         g_free (name);
3882                         g_free (sig);
3883                         m->table_idx = am->token & 0xffffff;
3884                         return am->token;
3885                 }
3886         }
3887         am = g_new0 (ArrayMethod, 1);
3888         am->name = name;
3889         am->sig = sig;
3890         am->parent = mtype;
3891         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3892                 method_encode_signature (assembly, sig));
3893         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3894         m->table_idx = am->token & 0xffffff;
3895         return am->token;
3896 fail:
3897         g_free (am);
3898         g_free (name);
3899         g_free (sig);
3900         return 0;
3901
3902 }
3903
3904 /*
3905  * Insert into the metadata tables all the info about the TypeBuilder tb.
3906  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3907  */
3908 static gboolean
3909 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3910 {
3911         MonoDynamicTable *table;
3912         guint *values;
3913         int i, is_object = 0, is_system = 0;
3914         char *n;
3915
3916         mono_error_init (error);
3917
3918         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3919         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3920         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3921         n = mono_string_to_utf8 (tb->name);
3922         if (strcmp (n, "Object") == 0)
3923                 is_object++;
3924         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3925         g_free (n);
3926         n = mono_string_to_utf8 (tb->nspace);
3927         if (strcmp (n, "System") == 0)
3928                 is_system++;
3929         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3930         g_free (n);
3931         if (tb->parent && !(is_system && is_object) && 
3932                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3933                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3934                 return_val_if_nok (error, FALSE);
3935                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3936         } else {
3937                 values [MONO_TYPEDEF_EXTENDS] = 0;
3938         }
3939         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3940         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3941
3942         /*
3943          * if we have explicitlayout or sequentiallayouts, output data in the
3944          * ClassLayout table.
3945          */
3946         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3947                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3948                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3949                 table->rows++;
3950                 alloc_table (table, table->rows);
3951                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3952                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3953                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3954                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3955         }
3956
3957         /* handle interfaces */
3958         if (tb->interfaces) {
3959                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3960                 i = table->rows;
3961                 table->rows += mono_array_length (tb->interfaces);
3962                 alloc_table (table, table->rows);
3963                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3964                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3965                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3966                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3967                         return_val_if_nok (error, FALSE);
3968                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3969                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3970                         values += MONO_INTERFACEIMPL_SIZE;
3971                 }
3972         }
3973
3974         /* handle fields */
3975         if (tb->fields) {
3976                 table = &assembly->tables [MONO_TABLE_FIELD];
3977                 table->rows += tb->num_fields;
3978                 alloc_table (table, table->rows);
3979                 for (i = 0; i < tb->num_fields; ++i) {
3980                         mono_image_get_field_info (
3981                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3982                         return_val_if_nok (error, FALSE);
3983                 }
3984         }
3985
3986         /* handle constructors */
3987         if (tb->ctors) {
3988                 table = &assembly->tables [MONO_TABLE_METHOD];
3989                 table->rows += mono_array_length (tb->ctors);
3990                 alloc_table (table, table->rows);
3991                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3992                         if (!mono_image_get_ctor_info (domain,
3993                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3994                                                        assembly, error))
3995                                 return FALSE;
3996                 }
3997         }
3998
3999         /* handle methods */
4000         if (tb->methods) {
4001                 table = &assembly->tables [MONO_TABLE_METHOD];
4002                 table->rows += tb->num_methods;
4003                 alloc_table (table, table->rows);
4004                 for (i = 0; i < tb->num_methods; ++i) {
4005                         if (!mono_image_get_method_info (
4006                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4007                                 return FALSE;
4008                 }
4009         }
4010
4011         /* Do the same with properties etc.. */
4012         if (tb->events && mono_array_length (tb->events)) {
4013                 table = &assembly->tables [MONO_TABLE_EVENT];
4014                 table->rows += mono_array_length (tb->events);
4015                 alloc_table (table, table->rows);
4016                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4017                 table->rows ++;
4018                 alloc_table (table, table->rows);
4019                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4020                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4021                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4022                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4023                         mono_image_get_event_info (
4024                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4025                         return_val_if_nok (error, FALSE);
4026                 }
4027         }
4028         if (tb->properties && mono_array_length (tb->properties)) {
4029                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4030                 table->rows += mono_array_length (tb->properties);
4031                 alloc_table (table, table->rows);
4032                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4033                 table->rows ++;
4034                 alloc_table (table, table->rows);
4035                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4036                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4037                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4038                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4039                         mono_image_get_property_info (
4040                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4041                         return_val_if_nok (error, FALSE);
4042                 }
4043         }
4044
4045         /* handle generic parameters */
4046         if (tb->generic_params) {
4047                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4048                 table->rows += mono_array_length (tb->generic_params);
4049                 alloc_table (table, table->rows);
4050                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4051                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4052
4053                         mono_image_get_generic_param_info (
4054                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4055                 }
4056         }
4057
4058         mono_image_add_decl_security (assembly, 
4059                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4060
4061         if (tb->subtypes) {
4062                 MonoDynamicTable *ntable;
4063                 
4064                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4065                 ntable->rows += mono_array_length (tb->subtypes);
4066                 alloc_table (ntable, ntable->rows);
4067                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4068
4069                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4070                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4071
4072                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4073                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4074                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4075                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4076                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4077                                 ntable->next_idx, ntable->rows);*/
4078                         values += MONO_NESTED_CLASS_SIZE;
4079                         ntable->next_idx++;
4080                 }
4081         }
4082
4083         return TRUE;
4084 }
4085 #endif
4086
4087 static void
4088 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4089 {
4090         int i;
4091
4092         mono_ptr_array_append (*types, type);
4093
4094         if (!type->subtypes)
4095                 return;
4096
4097         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4098                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4099                 collect_types (types, subtype);
4100         }
4101 }
4102
4103 static gint
4104 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4105 {
4106         if ((*type1)->table_idx < (*type2)->table_idx)
4107                 return -1;
4108         else
4109                 if ((*type1)->table_idx > (*type2)->table_idx)
4110                         return 1;
4111         else
4112                 return 0;
4113 }
4114
4115 static gboolean
4116 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4117         int i;
4118
4119         mono_error_init (error);
4120         if (!pinfo)
4121                 return TRUE;
4122         for (i = 0; i < mono_array_length (pinfo); ++i) {
4123                 MonoReflectionParamBuilder *pb;
4124                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4125                 if (!pb)
4126                         continue;
4127                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4128                         return FALSE;
4129         }
4130
4131         return TRUE;
4132 }
4133
4134 static gboolean
4135 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4136         int i;
4137
4138         mono_error_init (error);
4139         
4140         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4141                 return FALSE;
4142         if (tb->fields) {
4143                 for (i = 0; i < tb->num_fields; ++i) {
4144                         MonoReflectionFieldBuilder* fb;
4145                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4146                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4147                                 return FALSE;
4148                 }
4149         }
4150         if (tb->events) {
4151                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4152                         MonoReflectionEventBuilder* eb;
4153                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4154                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4155                                 return FALSE;
4156                 }
4157         }
4158         if (tb->properties) {
4159                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4160                         MonoReflectionPropertyBuilder* pb;
4161                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4162                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4163                                 return FALSE;
4164                 }
4165         }
4166         if (tb->ctors) {
4167                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4168                         MonoReflectionCtorBuilder* cb;
4169                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4170                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4171                             !params_add_cattrs (assembly, cb->pinfo, error))
4172                                 return FALSE;
4173                 }
4174         }
4175
4176         if (tb->methods) {
4177                 for (i = 0; i < tb->num_methods; ++i) {
4178                         MonoReflectionMethodBuilder* mb;
4179                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4180                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4181                             !params_add_cattrs (assembly, mb->pinfo, error))
4182                                 return FALSE;
4183                 }
4184         }
4185
4186         if (tb->subtypes) {
4187                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4188                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4189                                 return FALSE;
4190                 }
4191         }
4192
4193         return TRUE;
4194 }
4195
4196 static gboolean
4197 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4198 {
4199         int i;
4200         
4201         mono_error_init (error);
4202
4203         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4204                 return FALSE;
4205
4206         if (moduleb->global_methods) {
4207                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4208                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4209                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4210                             !params_add_cattrs (assembly, mb->pinfo, error))
4211                                 return FALSE;
4212                 }
4213         }
4214
4215         if (moduleb->global_fields) {
4216                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4217                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4218                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4219                                 return FALSE;
4220                 }
4221         }
4222         
4223         if (moduleb->types) {
4224                 for (i = 0; i < moduleb->num_types; ++i) {
4225                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4226                                 return FALSE;
4227                 }
4228         }
4229
4230         return TRUE;
4231 }
4232
4233 static void
4234 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4235 {
4236         MonoDynamicTable *table;
4237         guint32 *values;
4238         char blob_size [6];
4239         guchar hash [20];
4240         char *b = blob_size;
4241         char *dir, *path;
4242
4243         table = &assembly->tables [MONO_TABLE_FILE];
4244         table->rows++;
4245         alloc_table (table, table->rows);
4246         values = table->values + table->next_idx * MONO_FILE_SIZE;
4247         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4248         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4249         if (image_is_dynamic (module->image)) {
4250                 /* This depends on the fact that the main module is emitted last */
4251                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4252                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4253         } else {
4254                 dir = NULL;
4255                 path = g_strdup (module->image->name);
4256         }
4257         mono_sha1_get_digest_from_file (path, hash);
4258         g_free (dir);
4259         g_free (path);
4260         mono_metadata_encode_value (20, b, &b);
4261         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4262         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4263         table->next_idx ++;
4264 }
4265
4266 static void
4267 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4268 {
4269         MonoDynamicTable *table;
4270         int i;
4271
4272         table = &assembly->tables [MONO_TABLE_MODULE];
4273         mb->table_idx = table->next_idx ++;
4274         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4275         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4276         i /= 16;
4277         ++i;
4278         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4279         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4280         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4281         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4282 }
4283
4284 static guint32
4285 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4286         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4287 {
4288         MonoDynamicTable *table;
4289         guint32 *values;
4290         guint32 visib, res;
4291
4292         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4293         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4294                 return 0;
4295
4296         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4297         table->rows++;
4298         alloc_table (table, table->rows);
4299         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4300
4301         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4302         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4303         if (klass->nested_in)
4304                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4305         else
4306                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4307         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4308         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4309
4310         res = table->next_idx;
4311
4312         table->next_idx ++;
4313
4314         /* Emit nested types */
4315         if (klass->ext && klass->ext->nested_classes) {
4316                 GList *tmp;
4317
4318                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4319                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4320         }
4321
4322         return res;
4323 }
4324
4325 static void
4326 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4327                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4328                               MonoError *error)
4329 {
4330         MonoClass *klass;
4331         guint32 idx, i;
4332
4333         mono_error_init (error);
4334
4335         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4336         return_if_nok (error);
4337
4338         klass = mono_class_from_mono_type (t);
4339
4340         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4341
4342         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4343                                                                                                    parent_index, assembly);
4344
4345         /* 
4346          * Emit nested types
4347          * We need to do this ourselves since klass->nested_classes is not set up.
4348          */
4349         if (tb->subtypes) {
4350                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4351                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4352                         return_if_nok (error);
4353                 }
4354         }
4355 }
4356
4357 static void
4358 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4359         guint32 module_index, MonoDynamicImage *assembly)
4360 {
4361         MonoImage *image = module->image;
4362         MonoTableInfo  *t;
4363         guint32 i;
4364
4365         t = &image->tables [MONO_TABLE_TYPEDEF];
4366
4367         for (i = 0; i < t->rows; ++i) {
4368                 MonoError error;
4369                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4370                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4371
4372                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4373                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4374         }
4375 }
4376
4377 static void
4378 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4379 {
4380         MonoDynamicTable *table;
4381         guint32 *values;
4382         guint32 scope, scope_idx, impl, current_idx;
4383         gboolean forwarder = TRUE;
4384         gpointer iter = NULL;
4385         MonoClass *nested;
4386
4387         if (klass->nested_in) {
4388                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4389                 forwarder = FALSE;
4390         } else {
4391                 scope = resolution_scope_from_image (assembly, klass->image);
4392                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4393                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4394                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4395         }
4396
4397         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4398
4399         table->rows++;
4400         alloc_table (table, table->rows);
4401         current_idx = table->next_idx;
4402         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4403
4404         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4405         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4406         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4407         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4408         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4409
4410         table->next_idx++;
4411
4412         while ((nested = mono_class_get_nested_types (klass, &iter)))
4413                 add_exported_type (assemblyb, assembly, nested, current_idx);
4414 }
4415
4416 static void
4417 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4418 {
4419         MonoError error;
4420         MonoClass *klass;
4421         int i;
4422
4423         if (!assemblyb->type_forwarders)
4424                 return;
4425
4426         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4427                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4428                 MonoType *type;
4429                 if (!t)
4430                         continue;
4431
4432                 type = mono_reflection_type_get_handle (t, &error);
4433                 mono_error_assert_ok (&error);
4434                 g_assert (type);
4435
4436                 klass = mono_class_from_mono_type (type);
4437
4438                 add_exported_type (assemblyb, assembly, klass, 0);
4439         }
4440 }
4441
4442 #define align_pointer(base,p)\
4443         do {\
4444                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4445                 if (__diff & 3)\
4446                         (p) += 4 - (__diff & 3);\
4447         } while (0)
4448
4449 static int
4450 compare_constants (const void *a, const void *b)
4451 {
4452         const guint32 *a_values = (const guint32 *)a;
4453         const guint32 *b_values = (const guint32 *)b;
4454         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4455 }
4456
4457 static int
4458 compare_semantics (const void *a, const void *b)
4459 {
4460         const guint32 *a_values = (const guint32 *)a;
4461         const guint32 *b_values = (const guint32 *)b;
4462         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4463         if (assoc)
4464                 return assoc;
4465         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4466 }
4467
4468 static int
4469 compare_custom_attrs (const void *a, const void *b)
4470 {
4471         const guint32 *a_values = (const guint32 *)a;
4472         const guint32 *b_values = (const guint32 *)b;
4473
4474         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4475 }
4476
4477 static int
4478 compare_field_marshal (const void *a, const void *b)
4479 {
4480         const guint32 *a_values = (const guint32 *)a;
4481         const guint32 *b_values = (const guint32 *)b;
4482
4483         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4484 }
4485
4486 static int
4487 compare_nested (const void *a, const void *b)
4488 {
4489         const guint32 *a_values = (const guint32 *)a;
4490         const guint32 *b_values = (const guint32 *)b;
4491
4492         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4493 }
4494
4495 static int
4496 compare_genericparam (const void *a, const void *b)
4497 {
4498         MonoError error;
4499         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4500         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4501
4502         if ((*b_entry)->owner == (*a_entry)->owner) {
4503                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4504                 mono_error_assert_ok (&error);
4505                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4506                 mono_error_assert_ok (&error);
4507                 return 
4508                         mono_type_get_generic_param_num (a_type) -
4509                         mono_type_get_generic_param_num (b_type);
4510         } else
4511                 return (*a_entry)->owner - (*b_entry)->owner;
4512 }
4513
4514 static int
4515 compare_declsecurity_attrs (const void *a, const void *b)
4516 {
4517         const guint32 *a_values = (const guint32 *)a;
4518         const guint32 *b_values = (const guint32 *)b;
4519
4520         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4521 }
4522
4523 static int
4524 compare_interface_impl (const void *a, const void *b)
4525 {
4526         const guint32 *a_values = (const guint32 *)a;
4527         const guint32 *b_values = (const guint32 *)b;
4528
4529         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4530         if (klass)
4531                 return klass;
4532
4533         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4534 }
4535
4536 static void
4537 pad_heap (MonoDynamicStream *sh)
4538 {
4539         if (sh->index & 3) {
4540                 int sz = 4 - (sh->index & 3);
4541                 memset (sh->data + sh->index, 0, sz);
4542                 sh->index += sz;
4543         }
4544 }
4545
4546 struct StreamDesc {
4547         const char *name;
4548         MonoDynamicStream *stream;
4549 };
4550
4551 /*
4552  * build_compressed_metadata() fills in the blob of data that represents the 
4553  * raw metadata as it will be saved in the PE file. The five streams are output 
4554  * and the metadata tables are comnpressed from the guint32 array representation, 
4555  * to the compressed on-disk format.
4556  */
4557 static gboolean
4558 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4559 {
4560         MonoDynamicTable *table;
4561         int i;
4562         guint64 valid_mask = 0;
4563         guint64 sorted_mask;
4564         guint32 heapt_size = 0;
4565         guint32 meta_size = 256; /* allow for header and other stuff */
4566         guint32 table_offset;
4567         guint32 ntables = 0;
4568         guint64 *int64val;
4569         guint32 *int32val;
4570         guint16 *int16val;
4571         MonoImage *meta;
4572         unsigned char *p;
4573         struct StreamDesc stream_desc [5];
4574
4575         mono_error_init (error);
4576
4577         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4578         for (i = 0; i < assembly->gen_params->len; i++) {
4579                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4580                 if (!write_generic_param_entry (assembly, entry, error))
4581                         return FALSE;
4582         }
4583
4584         stream_desc [0].name  = "#~";
4585         stream_desc [0].stream = &assembly->tstream;
4586         stream_desc [1].name  = "#Strings";
4587         stream_desc [1].stream = &assembly->sheap;
4588         stream_desc [2].name  = "#US";
4589         stream_desc [2].stream = &assembly->us;
4590         stream_desc [3].name  = "#Blob";
4591         stream_desc [3].stream = &assembly->blob;
4592         stream_desc [4].name  = "#GUID";
4593         stream_desc [4].stream = &assembly->guid;
4594         
4595         /* tables that are sorted */
4596         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4597                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4598                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4599                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4600                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4601                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4602                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4603         
4604         /* Compute table sizes */
4605         /* the MonoImage has already been created in mono_image_basic_init() */
4606         meta = &assembly->image;
4607
4608         /* sizes should be multiple of 4 */
4609         pad_heap (&assembly->blob);
4610         pad_heap (&assembly->guid);
4611         pad_heap (&assembly->sheap);
4612         pad_heap (&assembly->us);
4613
4614         /* Setup the info used by compute_sizes () */
4615         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4616         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4617         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4618
4619         meta_size += assembly->blob.index;
4620         meta_size += assembly->guid.index;
4621         meta_size += assembly->sheap.index;
4622         meta_size += assembly->us.index;
4623
4624         for (i=0; i < MONO_TABLE_NUM; ++i)
4625                 meta->tables [i].rows = assembly->tables [i].rows;
4626         
4627         for (i = 0; i < MONO_TABLE_NUM; i++){
4628                 if (meta->tables [i].rows == 0)
4629                         continue;
4630                 valid_mask |= (guint64)1 << i;
4631                 ntables ++;
4632                 meta->tables [i].row_size = mono_metadata_compute_size (
4633                         meta, i, &meta->tables [i].size_bitfield);
4634                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4635         }
4636         heapt_size += 24; /* #~ header size */
4637         heapt_size += ntables * 4;
4638         /* make multiple of 4 */
4639         heapt_size += 3;
4640         heapt_size &= ~3;
4641         meta_size += heapt_size;
4642         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4643         p = (unsigned char*)meta->raw_metadata;
4644         /* the metadata signature */
4645         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4646         /* version numbers and 4 bytes reserved */
4647         int16val = (guint16*)p;
4648         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4649         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4650         p += 8;
4651         /* version string */
4652         int32val = (guint32*)p;
4653         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4654         p += 4;
4655         memcpy (p, meta->version, strlen (meta->version));
4656         p += GUINT32_FROM_LE (*int32val);
4657         align_pointer (meta->raw_metadata, p);
4658         int16val = (guint16*)p;
4659         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4660         *int16val = GUINT16_TO_LE (5); /* number of streams */
4661         p += 4;
4662
4663         /*
4664          * write the stream info.
4665          */
4666         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4667         table_offset += 3; table_offset &= ~3;
4668
4669         assembly->tstream.index = heapt_size;
4670         for (i = 0; i < 5; ++i) {
4671                 int32val = (guint32*)p;
4672                 stream_desc [i].stream->offset = table_offset;
4673                 *int32val++ = GUINT32_TO_LE (table_offset);
4674                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4675                 table_offset += GUINT32_FROM_LE (*int32val);
4676                 table_offset += 3; table_offset &= ~3;
4677                 p += 8;
4678                 strcpy ((char*)p, stream_desc [i].name);
4679                 p += strlen (stream_desc [i].name) + 1;
4680                 align_pointer (meta->raw_metadata, p);
4681         }
4682         /* 
4683          * now copy the data, the table stream header and contents goes first.
4684          */
4685         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4686         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4687         int32val = (guint32*)p;
4688         *int32val = GUINT32_TO_LE (0); /* reserved */
4689         p += 4;
4690
4691         *p++ = 2; /* version */
4692         *p++ = 0;
4693
4694         if (meta->idx_string_wide)
4695                 *p |= 0x01;
4696         if (meta->idx_guid_wide)
4697                 *p |= 0x02;
4698         if (meta->idx_blob_wide)
4699                 *p |= 0x04;
4700         ++p;
4701         *p++ = 1; /* reserved */
4702         int64val = (guint64*)p;
4703         *int64val++ = GUINT64_TO_LE (valid_mask);
4704         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4705         p += 16;
4706         int32val = (guint32*)p;
4707         for (i = 0; i < MONO_TABLE_NUM; i++){
4708                 if (meta->tables [i].rows == 0)
4709                         continue;
4710                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4711         }
4712         p = (unsigned char*)int32val;
4713
4714         /* sort the tables that still need sorting */
4715         table = &assembly->tables [MONO_TABLE_CONSTANT];
4716         if (table->rows)
4717                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4718         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4719         if (table->rows)
4720                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4721         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4722         if (table->rows)
4723                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4724         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4725         if (table->rows)
4726                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4727         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4728         if (table->rows)
4729                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4730         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4731         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4732         if (table->rows)
4733                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4734         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4735         if (table->rows)
4736                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4737
4738         /* compress the tables */
4739         for (i = 0; i < MONO_TABLE_NUM; i++){
4740                 int row, col;
4741                 guint32 *values;
4742                 guint32 bitfield = meta->tables [i].size_bitfield;
4743                 if (!meta->tables [i].rows)
4744                         continue;
4745                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4746                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4747                 meta->tables [i].base = (char*)p;
4748                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4749                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4750                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4751                                 switch (mono_metadata_table_size (bitfield, col)) {
4752                                 case 1:
4753                                         *p++ = values [col];
4754                                         break;
4755                                 case 2:
4756                                         *p++ = values [col] & 0xff;
4757                                         *p++ = (values [col] >> 8) & 0xff;
4758                                         break;
4759                                 case 4:
4760                                         *p++ = values [col] & 0xff;
4761                                         *p++ = (values [col] >> 8) & 0xff;
4762                                         *p++ = (values [col] >> 16) & 0xff;
4763                                         *p++ = (values [col] >> 24) & 0xff;
4764                                         break;
4765                                 default:
4766                                         g_assert_not_reached ();
4767                                 }
4768                         }
4769                 }
4770                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4771         }
4772         
4773         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4774         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4775         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4776         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4777         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4778
4779         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4780
4781         return TRUE;
4782 }
4783
4784 /*
4785  * Some tables in metadata need to be sorted according to some criteria, but
4786  * when methods and fields are first created with reflection, they may be assigned a token
4787  * that doesn't correspond to the final token they will get assigned after the sorting.
4788  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4789  * with the reflection objects that represent them. Once all the tables are set up, the 
4790  * reflection objects will contains the correct table index. fixup_method() will fixup the
4791  * tokens for the method with ILGenerator @ilgen.
4792  */
4793 static void
4794 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4795 {
4796         guint32 code_idx = GPOINTER_TO_UINT (value);
4797         MonoReflectionILTokenInfo *iltoken;
4798         MonoReflectionFieldBuilder *field;
4799         MonoReflectionCtorBuilder *ctor;
4800         MonoReflectionMethodBuilder *method;
4801         MonoReflectionTypeBuilder *tb;
4802         MonoReflectionArrayMethod *am;
4803         guint32 i, idx = 0;
4804         unsigned char *target;
4805
4806         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4807                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4808                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4809                 switch (target [3]) {
4810                 case MONO_TABLE_FIELD:
4811                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4812                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4813                                 idx = field->table_idx;
4814                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4815                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4816                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4817                         } else {
4818                                 g_assert_not_reached ();
4819                         }
4820                         break;
4821                 case MONO_TABLE_METHOD:
4822                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4823                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4824                                 idx = method->table_idx;
4825                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4826                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4827                                 idx = ctor->table_idx;
4828                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4829                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4830                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4831                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4832                         } else {
4833                                 g_assert_not_reached ();
4834                         }
4835                         break;
4836                 case MONO_TABLE_TYPEDEF:
4837                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4838                                 g_assert_not_reached ();
4839                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4840                         idx = tb->table_idx;
4841                         break;
4842                 case MONO_TABLE_MEMBERREF:
4843                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4844                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4845                                 idx = am->table_idx;
4846                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4847                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4848                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4849                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4850                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4851                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4852                                 continue;
4853                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4854                                 continue;
4855                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4856                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4857                                 g_assert (is_field_on_inst (f));
4858                                 continue;
4859                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4860                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4861                                 continue;
4862                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4863                                 continue;
4864                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4865                                 continue;
4866                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4867                                 continue;
4868                         } else {
4869                                 g_assert_not_reached ();
4870                         }
4871                         break;
4872                 case MONO_TABLE_METHODSPEC:
4873                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4874                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4875                                 g_assert (mono_method_signature (m)->generic_param_count);
4876                                 continue;
4877                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4878                                 continue;
4879                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4880                                 continue;
4881                         } else {
4882                                 g_assert_not_reached ();
4883                         }
4884                         break;
4885                 default:
4886                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4887                 }
4888                 target [0] = idx & 0xff;
4889                 target [1] = (idx >> 8) & 0xff;
4890                 target [2] = (idx >> 16) & 0xff;
4891         }
4892 }
4893
4894 /*
4895  * fixup_cattrs:
4896  *
4897  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4898  * value is not known when the table is emitted.
4899  */
4900 static void
4901 fixup_cattrs (MonoDynamicImage *assembly)
4902 {
4903         MonoDynamicTable *table;
4904         guint32 *values;
4905         guint32 type, i, idx, token;
4906         MonoObject *ctor;
4907
4908         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4909
4910         for (i = 0; i < table->rows; ++i) {
4911                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4912
4913                 type = values [MONO_CUSTOM_ATTR_TYPE];
4914                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4915                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4916                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4917                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4918                         g_assert (ctor);
4919
4920                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4921                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4922                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4923                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4924                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4925                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4926                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4927                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4928                         }
4929                 }
4930         }
4931 }
4932
4933 static void
4934 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4935 {
4936         MonoDynamicTable *table;
4937         guint32 *values;
4938
4939         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4940         table->rows++;
4941         alloc_table (table, table->rows);
4942         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4943         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4944         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4945         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4946         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4947         table->next_idx++;
4948 }
4949
4950 static void
4951 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4952 {
4953         MonoDynamicTable *table;
4954         guint32 *values;
4955         char blob_size [6];
4956         guchar hash [20];
4957         char *b = blob_size;
4958         char *name, *sname;
4959         guint32 idx, offset;
4960
4961         if (rsrc->filename) {
4962                 name = mono_string_to_utf8 (rsrc->filename);
4963                 sname = g_path_get_basename (name);
4964         
4965                 table = &assembly->tables [MONO_TABLE_FILE];
4966                 table->rows++;
4967                 alloc_table (table, table->rows);
4968                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4969                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4970                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4971                 g_free (sname);
4972
4973                 mono_sha1_get_digest_from_file (name, hash);
4974                 mono_metadata_encode_value (20, b, &b);
4975                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4976                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4977                 g_free (name);
4978                 idx = table->next_idx++;
4979                 rsrc->offset = 0;
4980                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4981         } else {
4982                 char sizebuf [4];
4983                 char *data;
4984                 guint len;
4985                 if (rsrc->data) {
4986                         data = mono_array_addr (rsrc->data, char, 0);
4987                         len = mono_array_length (rsrc->data);
4988                 } else {
4989                         data = NULL;
4990                         len = 0;
4991                 }
4992                 offset = len;
4993                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4994                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4995                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4996                 mono_image_add_stream_data (&assembly->resources, data, len);
4997
4998                 if (!mb->is_main)
4999                         /* 
5000                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5001                          * the main module, but that needs to reference the FILE table
5002                          * which isn't emitted yet.
5003                          */
5004                         return;
5005                 else
5006                         idx = 0;
5007         }
5008
5009         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5010 }
5011
5012 static void
5013 set_version_from_string (MonoString *version, guint32 *values)
5014 {
5015         gchar *ver, *p, *str;
5016         guint32 i;
5017         
5018         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5019         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5020         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5021         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5022         if (!version)
5023                 return;
5024         ver = str = mono_string_to_utf8 (version);
5025         for (i = 0; i < 4; ++i) {
5026                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5027                 switch (*p) {
5028                 case '.':
5029                         p++;
5030                         break;
5031                 case '*':
5032                         /* handle Revision and Build */
5033                         p++;
5034                         break;
5035                 }
5036                 ver = p;
5037         }
5038         g_free (str);
5039 }
5040
5041 static guint32
5042 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5043         gsize len;
5044         guint32 token = 0;
5045         char blob_size [6];
5046         char *b = blob_size;
5047
5048         if (!pkey)
5049                 return token;
5050
5051         len = mono_array_length (pkey);
5052         mono_metadata_encode_value (len, b, &b);
5053         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5054         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5055
5056         assembly->public_key = (guint8 *)g_malloc (len);
5057         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5058         assembly->public_key_len = len;
5059
5060         /* Special case: check for ECMA key (16 bytes) */
5061         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5062                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5063                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5064         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5065                 /* minimum key size (in 2.0) is 384 bits */
5066                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5067         } else {
5068                 /* FIXME - verifier */
5069                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5070                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5071         }
5072         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5073
5074         return token;
5075 }
5076
5077 static void
5078 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5079 {
5080         MonoDynamicTable *table;
5081         MonoDynamicImage *assembly;
5082         MonoReflectionAssemblyBuilder *assemblyb;
5083         MonoDomain *domain;
5084         guint32 *values;
5085         int i;
5086         guint32 module_index;
5087
5088         mono_error_init (error);
5089
5090         assemblyb = moduleb->assemblyb;
5091         assembly = moduleb->dynamic_image;
5092         domain = mono_object_domain (assemblyb);
5093
5094         /* Emit ASSEMBLY table */
5095         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5096         alloc_table (table, 1);
5097         values = table->values + MONO_ASSEMBLY_SIZE;
5098         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5099         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5100         if (assemblyb->culture) {
5101                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5102         } else {
5103                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5104         }
5105         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5106         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5107         set_version_from_string (assemblyb->version, values);
5108
5109         /* Emit FILE + EXPORTED_TYPE table */
5110         module_index = 0;
5111         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5112                 int j;
5113                 MonoReflectionModuleBuilder *file_module = 
5114                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5115                 if (file_module != moduleb) {
5116                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5117                         module_index ++;
5118                         if (file_module->types) {
5119                                 for (j = 0; j < file_module->num_types; ++j) {
5120                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5121                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5122                                         return_if_nok (error);
5123                                 }
5124                         }
5125                 }
5126         }
5127         if (assemblyb->loaded_modules) {
5128                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5129                         MonoReflectionModule *file_module = 
5130                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5131                         mono_image_fill_file_table (domain, file_module, assembly);
5132                         module_index ++;
5133                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5134                 }
5135         }
5136         if (assemblyb->type_forwarders)
5137                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5138
5139         /* Emit MANIFESTRESOURCE table */
5140         module_index = 0;
5141         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5142                 int j;
5143                 MonoReflectionModuleBuilder *file_module = 
5144                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5145                 /* The table for the main module is emitted later */
5146                 if (file_module != moduleb) {
5147                         module_index ++;
5148                         if (file_module->resources) {
5149                                 int len = mono_array_length (file_module->resources);
5150                                 for (j = 0; j < len; ++j) {
5151                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5152                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5153                                 }
5154                         }
5155                 }
5156         }               
5157 }
5158
5159 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5160
5161 /*
5162  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5163  * for the modulebuilder @moduleb.
5164  * At the end of the process, method and field tokens are fixed up and the 
5165  * on-disk compressed metadata representation is created.
5166  * Return TRUE on success, or FALSE on failure and sets @error
5167  */
5168 gboolean
5169 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5170 {
5171         MonoDynamicTable *table;
5172         MonoDynamicImage *assembly;
5173         MonoReflectionAssemblyBuilder *assemblyb;
5174         MonoDomain *domain;
5175         MonoPtrArray types;
5176         guint32 *values;
5177         int i, j;
5178
5179         mono_error_init (error);
5180
5181         assemblyb = moduleb->assemblyb;
5182         assembly = moduleb->dynamic_image;
5183         domain = mono_object_domain (assemblyb);
5184
5185         if (assembly->text_rva)
5186                 return TRUE;
5187
5188         assembly->text_rva = START_TEXT_RVA;
5189
5190         if (moduleb->is_main) {
5191                 mono_image_emit_manifest (moduleb, error);
5192                 return_val_if_nok (error, FALSE);
5193         }
5194
5195         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5196         table->rows = 1; /* .<Module> */
5197         table->next_idx++;
5198         alloc_table (table, table->rows);
5199         /*
5200          * Set the first entry.
5201          */
5202         values = table->values + table->columns;
5203         values [MONO_TYPEDEF_FLAGS] = 0;
5204         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5205         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5206         values [MONO_TYPEDEF_EXTENDS] = 0;
5207         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5208         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5209
5210         /* 
5211          * handle global methods 
5212          * FIXME: test what to do when global methods are defined in multiple modules.
5213          */
5214         if (moduleb->global_methods) {
5215                 table = &assembly->tables [MONO_TABLE_METHOD];
5216                 table->rows += mono_array_length (moduleb->global_methods);
5217                 alloc_table (table, table->rows);
5218                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5219                         if (!mono_image_get_method_info (
5220                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5221                                 goto leave;
5222                 }
5223         }
5224         if (moduleb->global_fields) {
5225                 table = &assembly->tables [MONO_TABLE_FIELD];
5226                 table->rows += mono_array_length (moduleb->global_fields);
5227                 alloc_table (table, table->rows);
5228                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5229                         mono_image_get_field_info (
5230                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5231                                 error);
5232                         if (!is_ok (error))
5233                                 goto leave;
5234                 }
5235         }
5236
5237         table = &assembly->tables [MONO_TABLE_MODULE];
5238         alloc_table (table, 1);
5239         mono_image_fill_module_table (domain, moduleb, assembly);
5240
5241         /* Collect all types into a list sorted by their table_idx */
5242         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5243
5244         if (moduleb->types)
5245                 for (i = 0; i < moduleb->num_types; ++i) {
5246                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5247                         collect_types (&types, type);
5248                 }
5249
5250         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5251         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5252         table->rows += mono_ptr_array_size (types);
5253         alloc_table (table, table->rows);
5254
5255         /*
5256          * Emit type names + namespaces at one place inside the string heap,
5257          * so load_class_names () needs to touch fewer pages.
5258          */
5259         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5260                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5261                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5262         }
5263         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5264                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5265                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5266         }
5267
5268         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5269                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5270                 if (!mono_image_get_type_info (domain, type, assembly, error))
5271                         goto leave_types;
5272         }
5273
5274         /* 
5275          * table->rows is already set above and in mono_image_fill_module_table.
5276          */
5277         /* add all the custom attributes at the end, once all the indexes are stable */
5278         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5279                 goto leave_types;
5280
5281         /* CAS assembly permissions */
5282         if (assemblyb->permissions_minimum)
5283                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5284         if (assemblyb->permissions_optional)
5285                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5286         if (assemblyb->permissions_refused)
5287                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5288
5289         if (!module_add_cattrs (assembly, moduleb, error))
5290                 goto leave_types;
5291
5292         /* fixup tokens */
5293         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5294
5295         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5296          * the final tokens and don't need another fixup pass. */
5297
5298         if (moduleb->global_methods) {
5299                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5300                         MonoReflectionMethodBuilder *mb = mono_array_get (
5301                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5302                         if (!mono_image_add_methodimpl (assembly, mb, error))
5303                                 goto leave_types;
5304                 }
5305         }
5306
5307         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5308                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5309                 if (type->methods) {
5310                         for (j = 0; j < type->num_methods; ++j) {
5311                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5312                                         type->methods, MonoReflectionMethodBuilder*, j);
5313
5314                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5315                                         goto leave_types;
5316                         }
5317                 }
5318         }
5319
5320         fixup_cattrs (assembly);
5321
5322 leave_types:
5323         mono_ptr_array_destroy (types);
5324 leave:
5325
5326         return mono_error_ok (error);
5327 }
5328
5329 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5330
5331 gboolean
5332 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5333 {
5334         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5335 }
5336
5337 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5338
5339
5340 typedef struct {
5341         guint32 import_lookup_table;
5342         guint32 timestamp;
5343         guint32 forwarder;
5344         guint32 name_rva;
5345         guint32 import_address_table_rva;
5346 } MonoIDT;
5347
5348 typedef struct {
5349         guint32 name_rva;
5350         guint32 flags;
5351 } MonoILT;
5352
5353 #ifndef DISABLE_REFLECTION_EMIT
5354
5355 /*
5356  * mono_image_insert_string:
5357  * @module: module builder object
5358  * @str: a string
5359  *
5360  * Insert @str into the user string stream of @module.
5361  */
5362 guint32
5363 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5364 {
5365         MonoDynamicImage *assembly;
5366         guint32 idx;
5367         char buf [16];
5368         char *b = buf;
5369         
5370         if (!module->dynamic_image)
5371                 mono_image_module_basic_init (module);
5372
5373         assembly = module->dynamic_image;
5374         
5375         if (assembly->save) {
5376                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5377                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5378 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5379         {
5380                 char *swapped = g_malloc (2 * mono_string_length (str));
5381                 const char *p = (const char*)mono_string_chars (str);
5382
5383                 swap_with_size (swapped, p, 2, mono_string_length (str));
5384                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5385                 g_free (swapped);
5386         }
5387 #else
5388                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5389 #endif
5390                 mono_image_add_stream_data (&assembly->us, "", 1);
5391         } else {
5392                 idx = assembly->us.index ++;
5393         }
5394
5395         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5396
5397         return MONO_TOKEN_STRING | idx;
5398 }
5399
5400 guint32
5401 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5402 {
5403         MonoClass *klass;
5404         guint32 token = 0;
5405         MonoMethodSignature *sig;
5406
5407         mono_error_init (error);
5408
5409         klass = obj->vtable->klass;
5410         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5411                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5412                 MonoMethodSignature *old;
5413                 guint32 sig_token, parent;
5414                 int nargs, i;
5415
5416                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5417
5418                 nargs = mono_array_length (opt_param_types);
5419                 old = mono_method_signature (method);
5420                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5421
5422                 sig->hasthis = old->hasthis;
5423                 sig->explicit_this = old->explicit_this;
5424                 sig->call_convention = old->call_convention;
5425                 sig->generic_param_count = old->generic_param_count;
5426                 sig->param_count = old->param_count + nargs;
5427                 sig->sentinelpos = old->param_count;
5428                 sig->ret = old->ret;
5429
5430                 for (i = 0; i < old->param_count; i++)
5431                         sig->params [i] = old->params [i];
5432
5433                 for (i = 0; i < nargs; i++) {
5434                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5435                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5436                         if (!is_ok (error)) goto fail;
5437                 }
5438
5439                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5440                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5441                 parent >>= MONO_TYPEDEFORREF_BITS;
5442
5443                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5444                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5445
5446                 sig_token = method_encode_signature (assembly, sig);
5447                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5448         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5449                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5450                 ReflectionMethodBuilder rmb;
5451                 guint32 parent, sig_token;
5452                 int nopt_args, nparams, ngparams, i;
5453
5454                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5455                         goto fail;
5456                 
5457                 rmb.opt_types = opt_param_types;
5458                 nopt_args = mono_array_length (opt_param_types);
5459
5460                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5461                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5462                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5463
5464                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5465                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5466                 sig->call_convention = rmb.call_conv;
5467                 sig->generic_param_count = ngparams;
5468                 sig->param_count = nparams + nopt_args;
5469                 sig->sentinelpos = nparams;
5470                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5471                 if (!is_ok (error)) goto fail;
5472
5473                 for (i = 0; i < nparams; i++) {
5474                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5475                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5476                         if (!is_ok (error)) goto fail;
5477                 }
5478
5479                 for (i = 0; i < nopt_args; i++) {
5480                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5481                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5482                         if (!is_ok (error)) goto fail;
5483                 }
5484
5485                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5486                 if (!is_ok (error))
5487                         goto fail;
5488
5489                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5490                 if (!mono_error_ok (error))
5491                         goto fail;
5492                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5493
5494                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5495                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5496
5497                 char *name = mono_string_to_utf8 (rmb.name);
5498                 token = mono_image_get_varargs_method_token (
5499                         assembly, parent, name, sig_token);
5500                 g_free (name);
5501         } else {
5502                 g_error ("requested method token for %s\n", klass->name);
5503         }
5504
5505         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5506         register_dyn_token (assembly, token, obj);
5507         return token;
5508 fail:
5509         g_assert (!mono_error_ok (error));
5510         return 0;
5511 }
5512
5513 /*
5514  * mono_image_create_token:
5515  * @assembly: a dynamic assembly
5516  * @obj:
5517  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5518  *
5519  * Get a token to insert in the IL code stream for the given MemberInfo.
5520  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5521  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5522  * entry.
5523  */
5524 guint32
5525 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5526                          gboolean create_open_instance, gboolean register_token,
5527                          MonoError *error)
5528 {
5529         MonoClass *klass;
5530         guint32 token = 0;
5531
5532         mono_error_init (error);
5533
5534         klass = obj->vtable->klass;
5535
5536         /* Check for user defined reflection objects */
5537         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5538         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5539                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5540                 return 0;
5541         }
5542
5543         if (strcmp (klass->name, "MethodBuilder") == 0) {
5544                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5545                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5546
5547                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5548                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5549                 else {
5550                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5551                         if (!mono_error_ok (error))
5552                                 return 0;
5553                 }
5554                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5555         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5556                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5557                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5558
5559                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5560                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5561                 else {
5562                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5563                         if (!mono_error_ok (error))
5564                                 return 0;
5565                 }
5566                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5567         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5568                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5569                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5570                 if (tb->generic_params) {
5571                         token = mono_image_get_generic_field_token (assembly, fb, error);
5572                         return_val_if_nok (error, 0);
5573                 } else {
5574                         if (tb->module->dynamic_image == assembly) {
5575                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5576                         } else {
5577                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5578                         }
5579                 }
5580         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5581                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5582                 if (create_open_instance && tb->generic_params) {
5583                         MonoType *type;
5584                         init_type_builder_generics (obj);
5585                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5586                         return_val_if_nok (error, 0);
5587                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5588                         token = mono_metadata_token_from_dor (token);
5589                 } else if (tb->module->dynamic_image == assembly) {
5590                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5591                 } else {
5592                         MonoType *type;
5593                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594                         return_val_if_nok (error, 0);
5595                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5596                 }
5597         } else if (strcmp (klass->name, "MonoType") == 0) {
5598                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5599                 return_val_if_nok (error, 0);
5600                 MonoClass *mc = mono_class_from_mono_type (type);
5601                 token = mono_metadata_token_from_dor (
5602                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5603         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5604                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5605                 return_val_if_nok (error, 0);
5606                 token = mono_metadata_token_from_dor (
5607                         mono_image_typedef_or_ref (assembly, type));
5608         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5609                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5610                 return_val_if_nok (error, 0);
5611                 token = mono_metadata_token_from_dor (
5612                         mono_image_typedef_or_ref (assembly, type));
5613         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5614                    strcmp (klass->name, "MonoMethod") == 0 ||
5615                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5616                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5617                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5618                 if (m->method->is_inflated) {
5619                         if (create_open_instance)
5620                                 token = mono_image_get_methodspec_token (assembly, m->method);
5621                         else
5622                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5623                 } else if ((m->method->klass->image == &assembly->image) &&
5624                          !m->method->klass->generic_class) {
5625                         static guint32 method_table_idx = 0xffffff;
5626                         if (m->method->klass->wastypebuilder) {
5627                                 /* we use the same token as the one that was assigned
5628                                  * to the Methodbuilder.
5629                                  * FIXME: do the equivalent for Fields.
5630                                  */
5631                                 token = m->method->token;
5632                         } else {
5633                                 /*
5634                                  * Each token should have a unique index, but the indexes are
5635                                  * assigned by managed code, so we don't know about them. An
5636                                  * easy solution is to count backwards...
5637                                  */
5638                                 method_table_idx --;
5639                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5640                         }
5641                 } else {
5642                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5643                 }
5644                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5645         } else if (strcmp (klass->name, "MonoField") == 0) {
5646                 MonoReflectionField *f = (MonoReflectionField *)obj;
5647                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5648                         static guint32 field_table_idx = 0xffffff;
5649                         field_table_idx --;
5650                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5651                 } else {
5652                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5653                 }
5654                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5655         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5656                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5657                 token = mono_image_get_array_token (assembly, m, error);
5658                 return_val_if_nok (error, 0);
5659         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5660                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5661                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5662                 return_val_if_nok (error, 0);
5663         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5664                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5665                 return_val_if_nok (error, 0);
5666                 token = mono_metadata_token_from_dor (
5667                         mono_image_typedef_or_ref (assembly, type));
5668         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5669                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5670                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5671                 return_val_if_nok (error, 0);
5672         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5673                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5674                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5675                 if (!mono_error_ok (error))
5676                         return 0;
5677         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5678                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5679                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5680                 if (!mono_error_ok (error))
5681                         return 0;
5682         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5683                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5684                 return_val_if_nok (error, 0);
5685                 token = mono_metadata_token_from_dor (
5686                                 mono_image_typedef_or_ref (assembly, type));
5687         } else {
5688                 g_error ("requested token for %s\n", klass->name);
5689         }
5690
5691         if (register_token)
5692                 mono_image_register_token (assembly, token, obj);
5693
5694         return token;
5695 }
5696
5697 /*
5698  * mono_image_register_token:
5699  *
5700  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5701  * the Module.ResolveXXXToken () methods to work.
5702  */
5703 void
5704 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5705 {
5706         MonoObject *prev;
5707
5708         dynamic_image_lock (assembly);
5709         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5710         if (prev) {
5711                 /* There could be multiple MethodInfo objects with the same token */
5712                 //g_assert (prev == obj);
5713         } else {
5714                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5715         }
5716         dynamic_image_unlock (assembly);
5717 }
5718
5719 static MonoDynamicImage*
5720 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5721 {
5722         static const guchar entrycode [16] = {0xff, 0x25, 0};
5723         MonoDynamicImage *image;
5724         int i;
5725
5726         const char *version;
5727
5728         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5729                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5730         else
5731                 version = mono_get_runtime_info ()->runtime_version;
5732
5733 #if HAVE_BOEHM_GC
5734         /* The MonoGHashTable's need GC tracking */
5735         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5736 #else
5737         image = g_new0 (MonoDynamicImage, 1);
5738 #endif
5739
5740         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5741         
5742         /*g_print ("created image %p\n", image);*/
5743         /* keep in sync with image.c */
5744         image->image.name = assembly_name;
5745         image->image.assembly_name = image->image.name; /* they may be different */
5746         image->image.module_name = module_name;
5747         image->image.version = g_strdup (version);
5748         image->image.md_version_major = 1;
5749         image->image.md_version_minor = 1;
5750         image->image.dynamic = TRUE;
5751
5752         image->image.references = g_new0 (MonoAssembly*, 1);
5753         image->image.references [0] = NULL;
5754
5755         mono_image_init (&image->image);
5756
5757         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");
5758         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5759         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5760         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5761         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5762         image->handleref = g_hash_table_new (NULL, NULL);
5763         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");
5764         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5765         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");
5766         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");
5767         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5769         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5770         image->gen_params = g_ptr_array_new ();
5771         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5772
5773         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5774         string_heap_init (&image->sheap);
5775         mono_image_add_stream_data (&image->us, "", 1);
5776         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5777         /* import tables... */
5778         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5779         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5780         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5781         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5782         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5783         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5784         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5785         stream_data_align (&image->code);
5786
5787         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5788
5789         for (i=0; i < MONO_TABLE_NUM; ++i) {
5790                 image->tables [i].next_idx = 1;
5791                 image->tables [i].columns = table_sizes [i];
5792         }
5793
5794         image->image.assembly = (MonoAssembly*)assembly;
5795         image->run = assembly->run;
5796         image->save = assembly->save;
5797         image->pe_kind = 0x1; /* ILOnly */
5798         image->machine = 0x14c; /* I386 */
5799         
5800         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5801
5802         dynamic_images_lock ();
5803
5804         if (!dynamic_images)
5805                 dynamic_images = g_ptr_array_new ();
5806
5807         g_ptr_array_add (dynamic_images, image);
5808
5809         dynamic_images_unlock ();
5810
5811         return image;
5812 }
5813 #endif
5814
5815 static void
5816 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5817 {
5818         g_free (key);
5819 }
5820
5821 static void
5822 release_hashtable (MonoGHashTable **hash)
5823 {
5824         if (*hash) {
5825                 mono_g_hash_table_destroy (*hash);
5826                 *hash = NULL;
5827         }
5828 }
5829
5830 void
5831 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5832 {
5833         release_hashtable (&image->token_fixups);
5834         release_hashtable (&image->handleref_managed);
5835         release_hashtable (&image->tokens);
5836         release_hashtable (&image->remapped_tokens);
5837         release_hashtable (&image->generic_def_objects);
5838         release_hashtable (&image->methodspec);
5839 }
5840
5841 // Free dynamic image pass one: Free resources but not image itself
5842 void
5843 mono_dynamic_image_free (MonoDynamicImage *image)
5844 {
5845         MonoDynamicImage *di = image;
5846         GList *list;
5847         int i;
5848
5849         if (di->methodspec)
5850                 mono_g_hash_table_destroy (di->methodspec);
5851         if (di->typespec)
5852                 g_hash_table_destroy (di->typespec);
5853         if (di->typeref)
5854                 g_hash_table_destroy (di->typeref);
5855         if (di->handleref)
5856                 g_hash_table_destroy (di->handleref);
5857         if (di->handleref_managed)
5858                 mono_g_hash_table_destroy (di->handleref_managed);
5859         if (di->tokens)
5860                 mono_g_hash_table_destroy (di->tokens);
5861         if (di->remapped_tokens)
5862                 mono_g_hash_table_destroy (di->remapped_tokens);
5863         if (di->generic_def_objects)
5864                 mono_g_hash_table_destroy (di->generic_def_objects);
5865         if (di->blob_cache) {
5866                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5867                 g_hash_table_destroy (di->blob_cache);
5868         }
5869         if (di->standalonesig_cache)
5870                 g_hash_table_destroy (di->standalonesig_cache);
5871         for (list = di->array_methods; list; list = list->next) {
5872                 ArrayMethod *am = (ArrayMethod *)list->data;
5873                 g_free (am->sig);
5874                 g_free (am->name);
5875                 g_free (am);
5876         }
5877         g_list_free (di->array_methods);
5878         if (di->gen_params) {
5879                 for (i = 0; i < di->gen_params->len; i++) {
5880                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5881                         mono_gc_deregister_root ((char*) &entry->gparam);
5882                         g_free (entry);
5883                 }
5884                 g_ptr_array_free (di->gen_params, TRUE);
5885         }
5886         if (di->token_fixups)
5887                 mono_g_hash_table_destroy (di->token_fixups);
5888         if (di->method_to_table_idx)
5889                 g_hash_table_destroy (di->method_to_table_idx);
5890         if (di->field_to_table_idx)
5891                 g_hash_table_destroy (di->field_to_table_idx);
5892         if (di->method_aux_hash)
5893                 g_hash_table_destroy (di->method_aux_hash);
5894         if (di->vararg_aux_hash)
5895                 g_hash_table_destroy (di->vararg_aux_hash);
5896         g_free (di->strong_name);
5897         g_free (di->win32_res);
5898         if (di->public_key)
5899                 g_free (di->public_key);
5900
5901         /*g_print ("string heap destroy for image %p\n", di);*/
5902         mono_dynamic_stream_reset (&di->sheap);
5903         mono_dynamic_stream_reset (&di->code);
5904         mono_dynamic_stream_reset (&di->resources);
5905         mono_dynamic_stream_reset (&di->us);
5906         mono_dynamic_stream_reset (&di->blob);
5907         mono_dynamic_stream_reset (&di->tstream);
5908         mono_dynamic_stream_reset (&di->guid);
5909         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5910                 g_free (di->tables [i].values);
5911         }
5912
5913         dynamic_images_lock ();
5914
5915         if (dynamic_images)
5916                 g_ptr_array_remove (dynamic_images, di);
5917
5918         dynamic_images_unlock ();
5919 }
5920
5921 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5922 void
5923 mono_dynamic_image_free_image (MonoDynamicImage *image)
5924 {
5925         /* See create_dynamic_mono_image () */
5926 #if HAVE_BOEHM_GC
5927         /* Allocated using GC_MALLOC */
5928 #else
5929         g_free (image);
5930 #endif
5931 }
5932
5933 #ifndef DISABLE_REFLECTION_EMIT
5934
5935 /*
5936  * mono_image_basic_init:
5937  * @assembly: an assembly builder object
5938  *
5939  * Create the MonoImage that represents the assembly builder and setup some
5940  * of the helper hash table and the basic metadata streams.
5941  */
5942 void
5943 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5944 {
5945         MonoDynamicAssembly *assembly;
5946         MonoDynamicImage *image;
5947         MonoDomain *domain = mono_object_domain (assemblyb);
5948         
5949         if (assemblyb->dynamic_assembly)
5950                 return;
5951
5952 #if HAVE_BOEHM_GC
5953         /* assembly->assembly.image might be GC allocated */
5954         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5955 #else
5956         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5957 #endif
5958
5959         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5960         
5961         assembly->assembly.ref_count = 1;
5962         assembly->assembly.dynamic = TRUE;
5963         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5964         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5965         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5966         if (assemblyb->culture)
5967                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5968         else
5969                 assembly->assembly.aname.culture = g_strdup ("");
5970
5971         if (assemblyb->version) {
5972                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5973                         char **version = g_strsplit (vstr, ".", 4);
5974                         char **parts = version;
5975                         assembly->assembly.aname.major = atoi (*parts++);
5976                         assembly->assembly.aname.minor = atoi (*parts++);
5977                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5978                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5979
5980                         g_strfreev (version);
5981                         g_free (vstr);
5982         } else {
5983                         assembly->assembly.aname.major = 0;
5984                         assembly->assembly.aname.minor = 0;
5985                         assembly->assembly.aname.build = 0;
5986                         assembly->assembly.aname.revision = 0;
5987         }
5988
5989         assembly->run = assemblyb->access != 2;
5990         assembly->save = assemblyb->access != 1;
5991         assembly->domain = domain;
5992
5993         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5994         image->initial_image = TRUE;
5995         assembly->assembly.aname.name = image->image.name;
5996         assembly->assembly.image = &image->image;
5997         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5998                 /* -1 to correct for the trailing NULL byte */
5999                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6000                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6001                 }
6002                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6003         }
6004
6005         mono_domain_assemblies_lock (domain);
6006         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6007         mono_domain_assemblies_unlock (domain);
6008
6009         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6010         
6011         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6012         
6013         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6014 }
6015
6016 #endif /* !DISABLE_REFLECTION_EMIT */
6017
6018 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6019
6020 static int
6021 calc_section_size (MonoDynamicImage *assembly)
6022 {
6023         int nsections = 0;
6024
6025         /* alignment constraints */
6026         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6027         g_assert ((assembly->code.index % 4) == 0);
6028         assembly->meta_size += 3;
6029         assembly->meta_size &= ~3;
6030         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6031         g_assert ((assembly->resources.index % 4) == 0);
6032
6033         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6034         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6035         nsections++;
6036
6037         if (assembly->win32_res) {
6038                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6039
6040                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6041                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6042                 nsections++;
6043         }
6044
6045         assembly->sections [MONO_SECTION_RELOC].size = 12;
6046         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6047         nsections++;
6048
6049         return nsections;
6050 }
6051
6052 typedef struct {
6053         guint32 id;
6054         guint32 offset;
6055         GSList *children;
6056         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6057 } ResTreeNode;
6058
6059 static int
6060 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6061 {
6062         ResTreeNode *t1 = (ResTreeNode*)a;
6063         ResTreeNode *t2 = (ResTreeNode*)b;
6064
6065         return t1->id - t2->id;
6066 }
6067
6068 /*
6069  * resource_tree_create:
6070  *
6071  *  Organize the resources into a resource tree.
6072  */
6073 static ResTreeNode *
6074 resource_tree_create (MonoArray *win32_resources)
6075 {
6076         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6077         GSList *l;
6078         int i;
6079
6080         tree = g_new0 (ResTreeNode, 1);
6081         
6082         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6083                 MonoReflectionWin32Resource *win32_res =
6084                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6085
6086                 /* Create node */
6087
6088                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6089                 lang_node = g_new0 (ResTreeNode, 1);
6090                 lang_node->id = win32_res->lang_id;
6091                 lang_node->win32_res = win32_res;
6092
6093                 /* Create type node if neccesary */
6094                 type_node = NULL;
6095                 for (l = tree->children; l; l = l->next)
6096                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6097                                 type_node = (ResTreeNode*)l->data;
6098                                 break;
6099                         }
6100
6101                 if (!type_node) {
6102                         type_node = g_new0 (ResTreeNode, 1);
6103                         type_node->id = win32_res->res_type;
6104
6105                         /* 
6106                          * The resource types have to be sorted otherwise
6107                          * Windows Explorer can't display the version information.
6108                          */
6109                         tree->children = g_slist_insert_sorted (tree->children, 
6110                                 type_node, resource_tree_compare_by_id);
6111                 }
6112
6113                 /* Create res node if neccesary */
6114                 res_node = NULL;
6115                 for (l = type_node->children; l; l = l->next)
6116                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6117                                 res_node = (ResTreeNode*)l->data;
6118                                 break;
6119                         }
6120
6121                 if (!res_node) {
6122                         res_node = g_new0 (ResTreeNode, 1);
6123                         res_node->id = win32_res->res_id;
6124                         type_node->children = g_slist_append (type_node->children, res_node);
6125                 }
6126
6127                 res_node->children = g_slist_append (res_node->children, lang_node);
6128         }
6129
6130         return tree;
6131 }
6132
6133 /*
6134  * resource_tree_encode:
6135  * 
6136  *   Encode the resource tree into the format used in the PE file.
6137  */
6138 static void
6139 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6140 {
6141         char *entries;
6142         MonoPEResourceDir dir;
6143         MonoPEResourceDirEntry dir_entry;
6144         MonoPEResourceDataEntry data_entry;
6145         GSList *l;
6146         guint32 res_id_entries;
6147
6148         /*
6149          * For the format of the resource directory, see the article
6150          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6151          * Matt Pietrek
6152          */
6153
6154         memset (&dir, 0, sizeof (dir));
6155         memset (&dir_entry, 0, sizeof (dir_entry));
6156         memset (&data_entry, 0, sizeof (data_entry));
6157
6158         g_assert (sizeof (dir) == 16);
6159         g_assert (sizeof (dir_entry) == 8);
6160         g_assert (sizeof (data_entry) == 16);
6161
6162         node->offset = p - begin;
6163
6164         /* IMAGE_RESOURCE_DIRECTORY */
6165         res_id_entries = g_slist_length (node->children);
6166         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6167
6168         memcpy (p, &dir, sizeof (dir));
6169         p += sizeof (dir);
6170
6171         /* Reserve space for entries */
6172         entries = p;
6173         p += sizeof (dir_entry) * res_id_entries;
6174
6175         /* Write children */
6176         for (l = node->children; l; l = l->next) {
6177                 ResTreeNode *child = (ResTreeNode*)l->data;
6178
6179                 if (child->win32_res) {
6180                         guint32 size;
6181
6182                         child->offset = p - begin;
6183
6184                         /* IMAGE_RESOURCE_DATA_ENTRY */
6185                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6186                         size = mono_array_length (child->win32_res->res_data);
6187                         data_entry.rde_size = GUINT32_TO_LE (size);
6188
6189                         memcpy (p, &data_entry, sizeof (data_entry));
6190                         p += sizeof (data_entry);
6191
6192                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6193                         p += size;
6194                 } else {
6195                         resource_tree_encode (child, begin, p, &p);
6196                 }
6197         }
6198
6199         /* IMAGE_RESOURCE_ENTRY */
6200         for (l = node->children; l; l = l->next) {
6201                 ResTreeNode *child = (ResTreeNode*)l->data;
6202
6203                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6204                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6205
6206                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6207                 entries += sizeof (dir_entry);
6208         }
6209
6210         *endbuf = p;
6211 }
6212
6213 static void
6214 resource_tree_free (ResTreeNode * node)
6215 {
6216         GSList * list;
6217         for (list = node->children; list; list = list->next)
6218                 resource_tree_free ((ResTreeNode*)list->data);
6219         g_slist_free(node->children);
6220         g_free (node);
6221 }
6222
6223 static void
6224 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6225 {
6226         char *buf;
6227         char *p;
6228         guint32 size, i;
6229         MonoReflectionWin32Resource *win32_res;
6230         ResTreeNode *tree;
6231
6232         if (!assemblyb->win32_resources)
6233                 return;
6234
6235         /*
6236          * Resources are stored in a three level tree inside the PE file.
6237          * - level one contains a node for each type of resource
6238          * - level two contains a node for each resource
6239          * - level three contains a node for each instance of a resource for a
6240          *   specific language.
6241          */
6242
6243         tree = resource_tree_create (assemblyb->win32_resources);
6244
6245         /* Estimate the size of the encoded tree */
6246         size = 0;
6247         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6248                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6249                 size += mono_array_length (win32_res->res_data);
6250         }
6251         /* Directory structure */
6252         size += mono_array_length (assemblyb->win32_resources) * 256;
6253         p = buf = (char *)g_malloc (size);
6254
6255         resource_tree_encode (tree, p, p, &p);
6256
6257         g_assert (p - buf <= size);
6258
6259         assembly->win32_res = (char *)g_malloc (p - buf);
6260         assembly->win32_res_size = p - buf;
6261         memcpy (assembly->win32_res, buf, p - buf);
6262
6263         g_free (buf);
6264         resource_tree_free (tree);
6265 }
6266
6267 static void
6268 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6269 {
6270         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6271         int i;
6272
6273         p += sizeof (MonoPEResourceDir);
6274         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6275                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6276                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6277                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6278                         fixup_resource_directory (res_section, child, rva);
6279                 } else {
6280                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6281                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6282                 }
6283
6284                 p += sizeof (MonoPEResourceDirEntry);
6285         }
6286 }
6287
6288 static void
6289 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6290 {
6291         guint32 dummy;
6292         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6293                 g_error ("WriteFile returned %d\n", GetLastError ());
6294 }
6295
6296 /*
6297  * mono_image_create_pefile:
6298  * @mb: a module builder object
6299  * 
6300  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6301  * assembly->pefile where it can be easily retrieved later in chunks.
6302  */
6303 gboolean
6304 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6305 {
6306         MonoMSDOSHeader *msdos;
6307         MonoDotNetHeader *header;
6308         MonoSectionTable *section;
6309         MonoCLIHeader *cli_header;
6310         guint32 size, image_size, virtual_base, text_offset;
6311         guint32 header_start, section_start, file_offset, virtual_offset;
6312         MonoDynamicImage *assembly;
6313         MonoReflectionAssemblyBuilder *assemblyb;
6314         MonoDynamicStream pefile_stream = {0};
6315         MonoDynamicStream *pefile = &pefile_stream;
6316         int i, nsections;
6317         guint32 *rva, value;
6318         guchar *p;
6319         static const unsigned char msheader[] = {
6320                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6321                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6323                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6324                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6325                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6326                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6327                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6328         };
6329
6330         mono_error_init (error);
6331
6332         assemblyb = mb->assemblyb;
6333
6334         mono_image_basic_init (assemblyb);
6335         assembly = mb->dynamic_image;
6336
6337         assembly->pe_kind = assemblyb->pe_kind;
6338         assembly->machine = assemblyb->machine;
6339         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6340         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6341         
6342         if (!mono_image_build_metadata (mb, error))
6343                 return FALSE;
6344         
6345
6346         if (mb->is_main && assemblyb->resources) {
6347                 int len = mono_array_length (assemblyb->resources);
6348                 for (i = 0; i < len; ++i)
6349                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6350         }
6351
6352         if (mb->resources) {
6353                 int len = mono_array_length (mb->resources);
6354                 for (i = 0; i < len; ++i)
6355                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6356         }
6357
6358         if (!build_compressed_metadata (assembly, error))
6359                 return FALSE;
6360
6361         if (mb->is_main)
6362                 assembly_add_win32_resources (assembly, assemblyb);
6363
6364         nsections = calc_section_size (assembly);
6365         
6366         /* The DOS header and stub */
6367         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6368         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6369
6370         /* the dotnet header */
6371         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6372
6373         /* the section tables */
6374         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6375
6376         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6377         virtual_offset = VIRT_ALIGN;
6378         image_size = 0;
6379
6380         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6381                 if (!assembly->sections [i].size)
6382                         continue;
6383                 /* align offsets */
6384                 file_offset += FILE_ALIGN - 1;
6385                 file_offset &= ~(FILE_ALIGN - 1);
6386                 virtual_offset += VIRT_ALIGN - 1;
6387                 virtual_offset &= ~(VIRT_ALIGN - 1);
6388
6389                 assembly->sections [i].offset = file_offset;
6390                 assembly->sections [i].rva = virtual_offset;
6391
6392                 file_offset += assembly->sections [i].size;
6393                 virtual_offset += assembly->sections [i].size;
6394                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6395         }
6396
6397         file_offset += FILE_ALIGN - 1;
6398         file_offset &= ~(FILE_ALIGN - 1);
6399
6400         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6401
6402         /* back-patch info */
6403         msdos = (MonoMSDOSHeader*)pefile->data;
6404         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6405
6406         header = (MonoDotNetHeader*)(pefile->data + header_start);
6407         header->pesig [0] = 'P';
6408         header->pesig [1] = 'E';
6409         
6410         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6411         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6412         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6413         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6414         if (assemblyb->pekind == 1) {
6415                 /* it's a dll */
6416                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6417         } else {
6418                 /* it's an exe */
6419                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6420         }
6421
6422         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6423
6424         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6425         header->pe.pe_major = 6;
6426         header->pe.pe_minor = 0;
6427         size = assembly->sections [MONO_SECTION_TEXT].size;
6428         size += FILE_ALIGN - 1;
6429         size &= ~(FILE_ALIGN - 1);
6430         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6431         size = assembly->sections [MONO_SECTION_RSRC].size;
6432         size += FILE_ALIGN - 1;
6433         size &= ~(FILE_ALIGN - 1);
6434         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6435         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6436         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6437         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6438         /* pe_rva_entry_point always at the beginning of the text section */
6439         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6440
6441         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6442         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6443         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6444         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6445         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6446         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6447         size = section_start;
6448         size += FILE_ALIGN - 1;
6449         size &= ~(FILE_ALIGN - 1);
6450         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6451         size = image_size;
6452         size += VIRT_ALIGN - 1;
6453         size &= ~(VIRT_ALIGN - 1);
6454         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6455
6456         /*
6457         // Translate the PEFileKind value to the value expected by the Windows loader
6458         */
6459         {
6460                 short kind;
6461
6462                 /*
6463                 // PEFileKinds.Dll == 1
6464                 // PEFileKinds.ConsoleApplication == 2
6465                 // PEFileKinds.WindowApplication == 3
6466                 //
6467                 // need to get:
6468                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6469                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6470                 */
6471                 if (assemblyb->pekind == 3)
6472                         kind = 2;
6473                 else
6474                         kind = 3;
6475                 
6476                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6477         }    
6478         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6479         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6480         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6481         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6482         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6483         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6484
6485         /* fill data directory entries */
6486
6487         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6488         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6489
6490         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6491         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6492
6493         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6494         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6495         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6496         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6497         /* patch entrypoint name */
6498         if (assemblyb->pekind == 1)
6499                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6500         else
6501                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6502         /* patch imported function RVA name */
6503         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6504         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6505
6506         /* the import table */
6507         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6508         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6509         /* patch imported dll RVA name and other entries in the dir */
6510         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6511         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6512         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6513         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6514         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6515         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6516
6517         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6518         value = (assembly->text_rva + assembly->imp_names_offset);
6519         *p++ = (value) & 0xff;
6520         *p++ = (value >> 8) & (0xff);
6521         *p++ = (value >> 16) & (0xff);
6522         *p++ = (value >> 24) & (0xff);
6523
6524         /* the CLI header info */
6525         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6526         cli_header->ch_size = GUINT32_FROM_LE (72);
6527         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6528         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6529         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6530         if (assemblyb->entry_point) {
6531                 guint32 table_idx = 0;
6532                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6533                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6534                         table_idx = methodb->table_idx;
6535                 } else {
6536                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6537                 }
6538                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6539         } else {
6540                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6541         }
6542         /* The embedded managed resources */
6543         text_offset = assembly->text_rva + assembly->code.index;
6544         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6545         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6546         text_offset += assembly->resources.index;
6547         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6548         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6549         text_offset += assembly->meta_size;
6550         if (assembly->strong_name_size) {
6551                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6552                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6553                 text_offset += assembly->strong_name_size;
6554         }
6555
6556         /* write the section tables and section content */
6557         section = (MonoSectionTable*)(pefile->data + section_start);
6558         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6559                 static const char section_names [][7] = {
6560                         ".text", ".rsrc", ".reloc"
6561                 };
6562                 if (!assembly->sections [i].size)
6563                         continue;
6564                 strcpy (section->st_name, section_names [i]);
6565                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6566                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6567                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6568                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6569                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6570                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6571                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6572                 section ++;
6573         }
6574         
6575         checked_write_file (file, pefile->data, pefile->index);
6576         
6577         mono_dynamic_stream_reset (pefile);
6578         
6579         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6580                 if (!assembly->sections [i].size)
6581                         continue;
6582                 
6583                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6584                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6585                 
6586                 switch (i) {
6587                 case MONO_SECTION_TEXT:
6588                         /* patch entry point */
6589                         p = (guchar*)(assembly->code.data + 2);
6590                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6591                         *p++ = (value) & 0xff;
6592                         *p++ = (value >> 8) & 0xff;
6593                         *p++ = (value >> 16) & 0xff;
6594                         *p++ = (value >> 24) & 0xff;
6595                 
6596                         checked_write_file (file, assembly->code.data, assembly->code.index);
6597                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6598                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6599                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6600                                 
6601
6602                         g_free (assembly->image.raw_metadata);
6603                         break;
6604                 case MONO_SECTION_RELOC: {
6605                         struct {
6606                                 guint32 page_rva;
6607                                 guint32 block_size;
6608                                 guint16 type_and_offset;
6609                                 guint16 term;
6610                         } reloc;
6611                         
6612                         g_assert (sizeof (reloc) == 12);
6613                         
6614                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6615                         reloc.block_size = GUINT32_FROM_LE (12);
6616                         
6617                         /* 
6618                          * the entrypoint is always at the start of the text section 
6619                          * 3 is IMAGE_REL_BASED_HIGHLOW
6620                          * 2 is patch_size_rva - text_rva
6621                          */
6622                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6623                         reloc.term = 0;
6624                         
6625                         checked_write_file (file, &reloc, sizeof (reloc));
6626                         
6627                         break;
6628                 }
6629                 case MONO_SECTION_RSRC:
6630                         if (assembly->win32_res) {
6631
6632                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6633                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6634                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6635                         }
6636                         break;
6637                 default:
6638                         g_assert_not_reached ();
6639                 }
6640         }
6641         
6642         /* check that the file is properly padded */
6643         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6644                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6645         if (! SetEndOfFile (file))
6646                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6647         
6648         mono_dynamic_stream_reset (&assembly->code);
6649         mono_dynamic_stream_reset (&assembly->us);
6650         mono_dynamic_stream_reset (&assembly->blob);
6651         mono_dynamic_stream_reset (&assembly->guid);
6652         mono_dynamic_stream_reset (&assembly->sheap);
6653
6654         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6655         g_hash_table_destroy (assembly->blob_cache);
6656         assembly->blob_cache = NULL;
6657
6658         return TRUE;
6659 }
6660
6661 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6662
6663 gboolean
6664 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6665 {
6666         g_assert_not_reached ();
6667 }
6668
6669 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6670
6671 #ifndef DISABLE_REFLECTION_EMIT
6672
6673 MonoReflectionModule *
6674 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6675 {
6676         char *name;
6677         MonoImage *image;
6678         MonoImageOpenStatus status;
6679         MonoDynamicAssembly *assembly;
6680         guint32 module_count;
6681         MonoImage **new_modules;
6682         gboolean *new_modules_loaded;
6683         
6684         mono_error_init (error);
6685         
6686         name = mono_string_to_utf8 (fileName);
6687
6688         image = mono_image_open (name, &status);
6689         if (!image) {
6690                 if (status == MONO_IMAGE_ERROR_ERRNO)
6691                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6692                 else
6693                         mono_error_set_bad_image_name (error, name, NULL);
6694                 g_free (name);
6695                 return NULL;
6696         }
6697
6698         g_free (name);
6699
6700         assembly = ab->dynamic_assembly;
6701         image->assembly = (MonoAssembly*)assembly;
6702
6703         module_count = image->assembly->image->module_count;
6704         new_modules = g_new0 (MonoImage *, module_count + 1);
6705         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6706
6707         if (image->assembly->image->modules)
6708                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6709         if (image->assembly->image->modules_loaded)
6710                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6711         new_modules [module_count] = image;
6712         new_modules_loaded [module_count] = TRUE;
6713         mono_image_addref (image);
6714
6715         g_free (image->assembly->image->modules);
6716         image->assembly->image->modules = new_modules;
6717         image->assembly->image->modules_loaded = new_modules_loaded;
6718         image->assembly->image->module_count ++;
6719
6720         mono_assembly_load_references (image, &status);
6721         if (status) {
6722                 mono_image_close (image);
6723                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6724                 return NULL;
6725         }
6726
6727         return mono_module_get_object_checked (mono_domain_get (), image, error);
6728 }
6729
6730 #endif /* DISABLE_REFLECTION_EMIT */
6731
6732 /*
6733  * We need to return always the same object for MethodInfo, FieldInfo etc..
6734  * but we need to consider the reflected type.
6735  * type uses a different hash, since it uses custom hash/equal functions.
6736  */
6737
6738 typedef struct {
6739         gpointer item;
6740         MonoClass *refclass;
6741 } ReflectedEntry;
6742
6743 static gboolean
6744 reflected_equal (gconstpointer a, gconstpointer b) {
6745         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6746         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6747
6748         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6749 }
6750
6751 static guint
6752 reflected_hash (gconstpointer a) {
6753         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6754         return mono_aligned_addr_hash (ea->item);
6755 }
6756
6757 #define CHECK_OBJECT(t,p,k)     \
6758         do {    \
6759                 t _obj; \
6760                 ReflectedEntry e;       \
6761                 e.item = (p);   \
6762                 e.refclass = (k);       \
6763                 mono_domain_lock (domain);      \
6764                 if (!domain->refobject_hash)    \
6765                         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");  \
6766                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6767                         mono_domain_unlock (domain);    \
6768                         return _obj;    \
6769                 }       \
6770         mono_domain_unlock (domain); \
6771         } while (0)
6772
6773 #ifdef HAVE_BOEHM_GC
6774 /* ReflectedEntry doesn't need to be GC tracked */
6775 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6776 #define FREE_REFENTRY(entry) g_free ((entry))
6777 #define REFENTRY_REQUIRES_CLEANUP
6778 #else
6779 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6780 /* FIXME: */
6781 #define FREE_REFENTRY(entry)
6782 #endif
6783
6784 #define CACHE_OBJECT(t,p,o,k)   \
6785         do {    \
6786                 t _obj; \
6787         ReflectedEntry pe; \
6788         pe.item = (p); \
6789         pe.refclass = (k); \
6790         mono_domain_lock (domain); \
6791                 if (!domain->refobject_hash)    \
6792                         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");  \
6793         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6794         if (!_obj) { \
6795                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6796                     e->item = (p);      \
6797                     e->refclass = (k);  \
6798                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6799             _obj = o; \
6800         } \
6801                 mono_domain_unlock (domain);    \
6802         return _obj; \
6803         } while (0)
6804
6805 static void
6806 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6807 {
6808         mono_domain_lock (domain);
6809         if (domain->refobject_hash) {
6810         ReflectedEntry pe;
6811                 gpointer orig_pe, orig_value;
6812
6813                 pe.item = o;
6814                 pe.refclass = klass;
6815                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6816                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6817                         FREE_REFENTRY (orig_pe);
6818                 }
6819         }
6820         mono_domain_unlock (domain);
6821 }
6822
6823 #ifdef REFENTRY_REQUIRES_CLEANUP
6824 static void
6825 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6826 {
6827         FREE_REFENTRY (key);
6828 }
6829 #endif
6830
6831 void
6832 mono_reflection_cleanup_domain (MonoDomain *domain)
6833 {
6834         if (domain->refobject_hash) {
6835 /*let's avoid scanning the whole hashtable if not needed*/
6836 #ifdef REFENTRY_REQUIRES_CLEANUP
6837                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6838 #endif
6839                 mono_g_hash_table_destroy (domain->refobject_hash);
6840                 domain->refobject_hash = NULL;
6841         }
6842 }
6843
6844 #ifndef DISABLE_REFLECTION_EMIT
6845 static gpointer
6846 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6847 {
6848         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6849 }
6850
6851 static gpointer
6852 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6853 {
6854         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6855 }
6856
6857 void
6858 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6859 {
6860         MonoDynamicImage *image = moduleb->dynamic_image;
6861         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6862         if (!image) {
6863                 MonoError error;
6864                 int module_count;
6865                 MonoImage **new_modules;
6866                 MonoImage *ass;
6867                 char *name, *fqname;
6868                 /*
6869                  * FIXME: we already created an image in mono_image_basic_init (), but
6870                  * we don't know which module it belongs to, since that is only 
6871                  * determined at assembly save time.
6872                  */
6873                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6874                 name = mono_string_to_utf8 (ab->name);
6875                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6876                 if (!mono_error_ok (&error)) {
6877                         g_free (name);
6878                         mono_error_raise_exception (&error);
6879                 }
6880                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6881
6882                 moduleb->module.image = &image->image;
6883                 moduleb->dynamic_image = image;
6884                 register_module (mono_object_domain (moduleb), moduleb, image);
6885
6886                 /* register the module with the assembly */
6887                 ass = ab->dynamic_assembly->assembly.image;
6888                 module_count = ass->module_count;
6889                 new_modules = g_new0 (MonoImage *, module_count + 1);
6890
6891                 if (ass->modules)
6892                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6893                 new_modules [module_count] = &image->image;
6894                 mono_image_addref (&image->image);
6895
6896                 g_free (ass->modules);
6897                 ass->modules = new_modules;
6898                 ass->module_count ++;
6899         }
6900 }
6901
6902 void
6903 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6904 {
6905         MonoDynamicImage *image = moduleb->dynamic_image;
6906
6907         g_assert (type->type);
6908         image->wrappers_type = mono_class_from_mono_type (type->type);
6909 }
6910
6911 #endif
6912
6913 /*
6914  * mono_assembly_get_object:
6915  * @domain: an app domain
6916  * @assembly: an assembly
6917  *
6918  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6919  */
6920 MonoReflectionAssembly*
6921 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6922 {
6923         MonoError error;
6924         MonoReflectionAssembly *result;
6925         result = mono_assembly_get_object_checked (domain, assembly, &error);
6926         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6927         return result;
6928 }
6929 /*
6930  * mono_assembly_get_object_checked:
6931  * @domain: an app domain
6932  * @assembly: an assembly
6933  *
6934  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6935  */
6936 MonoReflectionAssembly*
6937 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6938 {
6939         MonoReflectionAssembly *res;
6940         
6941         mono_error_init (error);
6942
6943         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6944         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6945         if (!res)
6946                 return NULL;
6947         res->assembly = assembly;
6948
6949         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6950 }
6951
6952
6953
6954 MonoReflectionModule*   
6955 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6956 {
6957         MonoError error;
6958         MonoReflectionModule *result;
6959         result = mono_module_get_object_checked (domain, image, &error);
6960         mono_error_raise_exception (&error);
6961         return result;
6962 }
6963
6964 MonoReflectionModule*
6965 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6966 {
6967         MonoReflectionModule *res;
6968         char* basename;
6969         
6970         mono_error_init (error);
6971         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6972         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6973         if (!res)
6974                 return NULL;
6975
6976         res->image = image;
6977         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6978         if (!assm_obj)
6979                 return NULL;
6980         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6981
6982         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6983         basename = g_path_get_basename (image->name);
6984         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6985         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6986         
6987         g_free (basename);
6988
6989         if (image->assembly->image == image) {
6990                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6991         } else {
6992                 int i;
6993                 res->token = 0;
6994                 if (image->assembly->image->modules) {
6995                         for (i = 0; i < image->assembly->image->module_count; i++) {
6996                                 if (image->assembly->image->modules [i] == image)
6997                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6998                         }
6999                         g_assert (res->token);
7000                 }
7001         }
7002
7003         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7004 }
7005
7006 MonoReflectionModule*
7007 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7008 {
7009         MonoError error;
7010         MonoReflectionModule *result;
7011         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7012         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7013         return result;
7014 }
7015
7016 MonoReflectionModule*
7017 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7018 {
7019         MonoReflectionModule *res;
7020         MonoTableInfo *table;
7021         guint32 cols [MONO_FILE_SIZE];
7022         const char *name;
7023         guint32 i, name_idx;
7024         const char *val;
7025         
7026         mono_error_init (error);
7027
7028         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7029         if (!res)
7030                 return NULL;
7031
7032         table = &image->tables [MONO_TABLE_FILE];
7033         g_assert (table_index < table->rows);
7034         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7035
7036         res->image = NULL;
7037         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7038         if (!assm_obj)
7039                 return NULL;
7040         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7041         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7042
7043         /* Check whenever the row has a corresponding row in the moduleref table */
7044         table = &image->tables [MONO_TABLE_MODULEREF];
7045         for (i = 0; i < table->rows; ++i) {
7046                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7047                 val = mono_metadata_string_heap (image, name_idx);
7048                 if (strcmp (val, name) == 0)
7049                         res->image = image->modules [i];
7050         }
7051
7052         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7053         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7054         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7055         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7056         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7057
7058         return res;
7059 }
7060
7061 static gboolean
7062 verify_safe_for_managed_space (MonoType *type)
7063 {
7064         switch (type->type) {
7065 #ifdef DEBUG_HARDER
7066         case MONO_TYPE_ARRAY:
7067                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7068         case MONO_TYPE_PTR:
7069                 return verify_safe_for_managed_space (type->data.type);
7070         case MONO_TYPE_SZARRAY:
7071                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7072         case MONO_TYPE_GENERICINST: {
7073                 MonoGenericInst *inst = type->data.generic_class->inst;
7074                 int i;
7075                 if (!inst->is_open)
7076                         break;
7077                 for (i = 0; i < inst->type_argc; ++i)
7078                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7079                                 return FALSE;
7080                 return TRUE;
7081         }
7082 #endif
7083         case MONO_TYPE_VAR:
7084         case MONO_TYPE_MVAR:
7085                 return TRUE;
7086         default:
7087                 return TRUE;
7088         }
7089 }
7090
7091 static MonoType*
7092 mono_type_normalize (MonoType *type)
7093 {
7094         int i;
7095         MonoGenericClass *gclass;
7096         MonoGenericInst *ginst;
7097         MonoClass *gtd;
7098         MonoGenericContainer *gcontainer;
7099         MonoType **argv = NULL;
7100         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7101
7102         if (type->type != MONO_TYPE_GENERICINST)
7103                 return type;
7104
7105         gclass = type->data.generic_class;
7106         ginst = gclass->context.class_inst;
7107         if (!ginst->is_open)
7108                 return type;
7109
7110         gtd = gclass->container_class;
7111         gcontainer = gtd->generic_container;
7112         argv = g_newa (MonoType*, ginst->type_argc);
7113
7114         for (i = 0; i < ginst->type_argc; ++i) {
7115                 MonoType *t = ginst->type_argv [i], *norm;
7116                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7117                         is_denorm_gtd = FALSE;
7118                 norm = mono_type_normalize (t);
7119                 argv [i] = norm;
7120                 if (norm != t)
7121                         requires_rebind = TRUE;
7122         }
7123
7124         if (is_denorm_gtd)
7125                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7126
7127         if (requires_rebind) {
7128                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7129                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7130         }
7131
7132         return type;
7133 }
7134 /*
7135  * mono_type_get_object:
7136  * @domain: an app domain
7137  * @type: a type
7138  *
7139  * Return an System.MonoType object representing the type @type.
7140  */
7141 MonoReflectionType*
7142 mono_type_get_object (MonoDomain *domain, MonoType *type)
7143 {
7144         MonoError error;
7145         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7146         mono_error_raise_exception (&error);
7147
7148         return ret;
7149 }
7150
7151 MonoReflectionType*
7152 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7153 {
7154         MonoType *norm_type;
7155         MonoReflectionType *res;
7156         MonoClass *klass;
7157
7158         mono_error_init (error);
7159
7160         klass = mono_class_from_mono_type (type);
7161
7162         /*we must avoid using @type as it might have come
7163          * from a mono_metadata_type_dup and the caller
7164          * expects that is can be freed.
7165          * Using the right type from 
7166          */
7167         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7168
7169         /* void is very common */
7170         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7171                 return (MonoReflectionType*)domain->typeof_void;
7172
7173         /*
7174          * If the vtable of the given class was already created, we can use
7175          * the MonoType from there and avoid all locking and hash table lookups.
7176          * 
7177          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7178          * that the resulting object is different.   
7179          */
7180         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7181                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7182                 if (vtable && vtable->type)
7183                         return (MonoReflectionType *)vtable->type;
7184         }
7185
7186         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7187         mono_domain_lock (domain);
7188         if (!domain->type_hash)
7189                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7190                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7191         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7192                 mono_domain_unlock (domain);
7193                 mono_loader_unlock ();
7194                 return res;
7195         }
7196
7197         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7198          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7199          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7200          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7201          * artifact of how generics are encoded and should be transparent to managed code so we
7202          * need to weed out this diference when retrieving managed System.Type objects.
7203          */
7204         norm_type = mono_type_normalize (type);
7205         if (norm_type != type) {
7206                 res = mono_type_get_object_checked (domain, norm_type, error);
7207                 if (!mono_error_ok (error))
7208                         return NULL;
7209                 mono_g_hash_table_insert (domain->type_hash, type, res);
7210                 mono_domain_unlock (domain);
7211                 mono_loader_unlock ();
7212                 return res;
7213         }
7214
7215         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7216         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7217                 g_assert (0);
7218
7219         if (!verify_safe_for_managed_space (type)) {
7220                 mono_domain_unlock (domain);
7221                 mono_loader_unlock ();
7222                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7223                 return NULL;
7224         }
7225
7226         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7227                 gboolean is_type_done = TRUE;
7228                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7229                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7230                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7231                 */
7232                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7233                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7234
7235                         if (gparam->owner && gparam->owner->is_method) {
7236                                 MonoMethod *method = gparam->owner->owner.method;
7237                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7238                                         is_type_done = FALSE;
7239                         } else if (gparam->owner && !gparam->owner->is_method) {
7240                                 MonoClass *klass = gparam->owner->owner.klass;
7241                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7242                                         is_type_done = FALSE;
7243                         }
7244                 } 
7245
7246                 /* g_assert_not_reached (); */
7247                 /* should this be considered an error condition? */
7248                 if (is_type_done && !type->byref) {
7249                         mono_domain_unlock (domain);
7250                         mono_loader_unlock ();
7251                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7252                 }
7253         }
7254         /* This is stored in vtables/JITted code so it has to be pinned */
7255         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7256         if (!mono_error_ok (error))
7257                 return NULL;
7258
7259         res->type = type;
7260         mono_g_hash_table_insert (domain->type_hash, type, res);
7261
7262         if (type->type == MONO_TYPE_VOID)
7263                 domain->typeof_void = (MonoObject*)res;
7264
7265         mono_domain_unlock (domain);
7266         mono_loader_unlock ();
7267         return res;
7268 }
7269
7270 /*
7271  * mono_method_get_object:
7272  * @domain: an app domain
7273  * @method: a method
7274  * @refclass: the reflected type (can be NULL)
7275  *
7276  * Return an System.Reflection.MonoMethod object representing the method @method.
7277  */
7278 MonoReflectionMethod*
7279 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7280 {
7281         MonoError error;
7282         MonoReflectionMethod *ret = NULL;
7283         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7284         mono_error_raise_exception (&error);
7285         return ret;
7286 }
7287
7288 /*
7289  * mono_method_get_object_checked:
7290  * @domain: an app domain
7291  * @method: a method
7292  * @refclass: the reflected type (can be NULL)
7293  * @error: set on error.
7294  *
7295  * Return an System.Reflection.MonoMethod object representing the method @method.
7296  * Returns NULL and sets @error on error.
7297  */
7298 MonoReflectionMethod*
7299 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7300 {
7301         /*
7302          * We use the same C representation for methods and constructors, but the type 
7303          * name in C# is different.
7304          */
7305         MonoReflectionType *rt;
7306         MonoClass *klass;
7307         MonoReflectionMethod *ret;
7308
7309         mono_error_init (error);
7310
7311         if (method->is_inflated) {
7312                 MonoReflectionGenericMethod *gret;
7313
7314                 if (!refclass)
7315                         refclass = method->klass;
7316                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7317                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7318                         klass = mono_class_get_mono_generic_cmethod_class ();
7319                 } else {
7320                         klass = mono_class_get_mono_generic_method_class ();
7321                 }
7322                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7323                 if (!mono_error_ok (error))
7324                         goto leave;
7325                 gret->method.method = method;
7326
7327                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7328
7329                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7330                 if (!mono_error_ok (error))
7331                     goto leave;
7332
7333                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7334
7335                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7336         }
7337
7338         if (!refclass)
7339                 refclass = method->klass;
7340
7341         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7342         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7343                 klass = mono_class_get_mono_cmethod_class ();
7344         }
7345         else {
7346                 klass = mono_class_get_mono_method_class ();
7347         }
7348         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7349         if (!mono_error_ok (error))
7350                 goto leave;
7351         ret->method = method;
7352
7353         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7354         if (!mono_error_ok (error))
7355                 goto leave;
7356
7357         MONO_OBJECT_SETREF (ret, reftype, rt);
7358
7359         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7360
7361 leave:
7362         g_assert (!mono_error_ok (error));
7363         return NULL;
7364 }
7365
7366 /*
7367  * mono_method_clear_object:
7368  *
7369  *   Clear the cached reflection objects for the dynamic method METHOD.
7370  */
7371 void
7372 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7373 {
7374         MonoClass *klass;
7375         g_assert (method_is_dynamic (method));
7376
7377         klass = method->klass;
7378         while (klass) {
7379                 clear_cached_object (domain, method, klass);
7380                 klass = klass->parent;
7381         }
7382         /* Added by mono_param_get_objects () */
7383         clear_cached_object (domain, &(method->signature), NULL);
7384         klass = method->klass;
7385         while (klass) {
7386                 clear_cached_object (domain, &(method->signature), klass);
7387                 klass = klass->parent;
7388         }
7389 }
7390
7391 /*
7392  * mono_field_get_object:
7393  * @domain: an app domain
7394  * @klass: a type
7395  * @field: a field
7396  *
7397  * Return an System.Reflection.MonoField object representing the field @field
7398  * in class @klass.
7399  */
7400 MonoReflectionField*
7401 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7402 {
7403         MonoError error;
7404         MonoReflectionField *result;
7405         result = mono_field_get_object_checked (domain, klass, field, &error);
7406         mono_error_raise_exception (&error);
7407         return result;
7408 }
7409
7410 /*
7411  * mono_field_get_object_checked:
7412  * @domain: an app domain
7413  * @klass: a type
7414  * @field: a field
7415  * @error: set on error
7416  *
7417  * Return an System.Reflection.MonoField object representing the field @field
7418  * in class @klass. On error, returns NULL and sets @error.
7419  */
7420 MonoReflectionField*
7421 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7422 {
7423         MonoReflectionType *rt;
7424         MonoReflectionField *res;
7425
7426         mono_error_init (error);
7427
7428         CHECK_OBJECT (MonoReflectionField *, field, klass);
7429         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7430         if (!res)
7431                 return NULL;
7432         res->klass = klass;
7433         res->field = field;
7434         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7435
7436         if (is_field_on_inst (field)) {
7437                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7438
7439                 rt = mono_type_get_object_checked (domain, field->type, error);
7440                 if (!mono_error_ok (error))
7441                         return NULL;
7442
7443                 MONO_OBJECT_SETREF (res, type, rt);
7444         } else {
7445                 if (field->type) {
7446                         rt = mono_type_get_object_checked (domain, field->type, error);
7447                         if (!mono_error_ok (error))
7448                                 return NULL;
7449
7450                         MONO_OBJECT_SETREF (res, type, rt);
7451                 }
7452                 res->attrs = mono_field_get_flags (field);
7453         }
7454         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7455 }
7456
7457 /*
7458  * mono_property_get_object:
7459  * @domain: an app domain
7460  * @klass: a type
7461  * @property: a property
7462  *
7463  * Return an System.Reflection.MonoProperty object representing the property @property
7464  * in class @klass.
7465  */
7466 MonoReflectionProperty*
7467 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7468 {
7469         MonoError error;
7470         MonoReflectionProperty *result;
7471         result = mono_property_get_object_checked (domain, klass, property, &error);
7472         mono_error_raise_exception (&error);
7473         return result;
7474 }
7475
7476 /**
7477  * mono_property_get_object:
7478  * @domain: an app domain
7479  * @klass: a type
7480  * @property: a property
7481  * @error: set on error
7482  *
7483  * Return an System.Reflection.MonoProperty object representing the property @property
7484  * in class @klass.  On error returns NULL and sets @error.
7485  */
7486 MonoReflectionProperty*
7487 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7488 {
7489         MonoReflectionProperty *res;
7490
7491         mono_error_init (error);
7492
7493         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7494         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7495         if (!res)
7496                 return NULL;
7497         res->klass = klass;
7498         res->property = property;
7499         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7500 }
7501
7502 /*
7503  * mono_event_get_object:
7504  * @domain: an app domain
7505  * @klass: a type
7506  * @event: a event
7507  *
7508  * Return an System.Reflection.MonoEvent object representing the event @event
7509  * in class @klass.
7510  */
7511 MonoReflectionEvent*
7512 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7513 {
7514         MonoError error;
7515         MonoReflectionEvent *result;
7516         result = mono_event_get_object_checked (domain, klass, event, &error);
7517         mono_error_raise_exception (&error);
7518         return result;
7519 }
7520
7521 /**
7522  * mono_event_get_object_checked:
7523  * @domain: an app domain
7524  * @klass: a type
7525  * @event: a event
7526  * @error: set on error
7527  *
7528  * Return an System.Reflection.MonoEvent object representing the event @event
7529  * in class @klass. On failure sets @error and returns NULL
7530  */
7531 MonoReflectionEvent*
7532 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7533 {
7534         MonoReflectionEvent *res;
7535         MonoReflectionMonoEvent *mono_event;
7536
7537         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7538         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7539         if (!mono_event)
7540                 return NULL;
7541         mono_event->klass = klass;
7542         mono_event->event = event;
7543         res = (MonoReflectionEvent*)mono_event;
7544         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7545 }
7546
7547 /**
7548  * mono_get_reflection_missing_object:
7549  * @domain: Domain where the object lives
7550  *
7551  * Returns the System.Reflection.Missing.Value singleton object
7552  * (of type System.Reflection.Missing).
7553  *
7554  * Used as the value for ParameterInfo.DefaultValue when Optional
7555  * is present
7556  */
7557 static MonoObject *
7558 mono_get_reflection_missing_object (MonoDomain *domain)
7559 {
7560         MonoError error;
7561         MonoObject *obj;
7562         static MonoClassField *missing_value_field = NULL;
7563         
7564         if (!missing_value_field) {
7565                 MonoClass *missing_klass;
7566                 missing_klass = mono_class_get_missing_class ();
7567                 mono_class_init (missing_klass);
7568                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7569                 g_assert (missing_value_field);
7570         }
7571         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7572         mono_error_assert_ok (&error);
7573         return obj;
7574 }
7575
7576 static MonoObject*
7577 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7578 {
7579         if (!*dbnull)
7580                 *dbnull = mono_get_dbnull_object (domain);
7581         return *dbnull;
7582 }
7583
7584 static MonoObject*
7585 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7586 {
7587         if (!*reflection_missing)
7588                 *reflection_missing = mono_get_reflection_missing_object (domain);
7589         return *reflection_missing;
7590 }
7591
7592 /*
7593  * mono_param_get_objects:
7594  * @domain: an app domain
7595  * @method: a method
7596  *
7597  * Return an System.Reflection.ParameterInfo array object representing the parameters
7598  * in the method @method.
7599  */
7600 MonoArray*
7601 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7602 {
7603         static MonoClass *System_Reflection_ParameterInfo;
7604         static MonoClass *System_Reflection_ParameterInfo_array;
7605         MonoArray *res = NULL;
7606         MonoReflectionMethod *member = NULL;
7607         MonoReflectionParameter *param = NULL;
7608         char **names = NULL, **blobs = NULL;
7609         guint32 *types = NULL;
7610         MonoType *type = NULL;
7611         MonoObject *dbnull = NULL;
7612         MonoObject *missing = NULL;
7613         MonoMarshalSpec **mspecs = NULL;
7614         MonoMethodSignature *sig = NULL;
7615         MonoVTable *pinfo_vtable;
7616         MonoReflectionType *rt;
7617         int i;
7618
7619         mono_error_init (error);
7620         
7621         if (!System_Reflection_ParameterInfo_array) {
7622                 MonoClass *klass;
7623
7624                 klass = mono_class_get_mono_parameter_info_class ();
7625
7626                 mono_memory_barrier ();
7627                 System_Reflection_ParameterInfo = klass; 
7628
7629         
7630                 klass = mono_array_class_get (klass, 1);
7631                 mono_memory_barrier ();
7632                 System_Reflection_ParameterInfo_array = klass;
7633         }
7634
7635         sig = mono_method_signature_checked (method, error);
7636         if (!mono_error_ok (error))
7637                 goto leave;
7638
7639         if (!sig->param_count) {
7640                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7641                 if (!res)
7642                         goto leave;
7643
7644                 return res;
7645         }
7646
7647         /* Note: the cache is based on the address of the signature into the method
7648          * since we already cache MethodInfos with the method as keys.
7649          */
7650         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7651
7652         member = mono_method_get_object_checked (domain, method, refclass, error);
7653         if (!member)
7654                 goto leave;
7655         names = g_new (char *, sig->param_count);
7656         mono_method_get_param_names (method, (const char **) names);
7657
7658         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7659         mono_method_get_marshal_info (method, mspecs);
7660
7661         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7662         if (!res)
7663                 goto leave;
7664
7665         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7666         for (i = 0; i < sig->param_count; ++i) {
7667                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7668                 if (!param)
7669                         goto leave;
7670
7671                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7672                 if (!rt)
7673                         goto leave;
7674
7675                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7676
7677                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7678
7679                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7680
7681                 param->PositionImpl = i;
7682                 param->AttrsImpl = sig->params [i]->attrs;
7683
7684                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7685                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7686                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7687                         else
7688                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7689                 } else {
7690
7691                         if (!blobs) {
7692                                 blobs = g_new0 (char *, sig->param_count);
7693                                 types = g_new0 (guint32, sig->param_count);
7694                                 get_default_param_value_blobs (method, blobs, types); 
7695                         }
7696
7697                         /* Build MonoType for the type from the Constant Table */
7698                         if (!type)
7699                                 type = g_new0 (MonoType, 1);
7700                         type->type = (MonoTypeEnum)types [i];
7701                         type->data.klass = NULL;
7702                         if (types [i] == MONO_TYPE_CLASS)
7703                                 type->data.klass = mono_defaults.object_class;
7704                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7705                                 /* For enums, types [i] contains the base type */
7706
7707                                         type->type = MONO_TYPE_VALUETYPE;
7708                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7709                         } else
7710                                 type->data.klass = mono_class_from_mono_type (type);
7711
7712                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7713                         if (!is_ok (error))
7714                                 goto leave;
7715                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7716
7717                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7718                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7719                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7720                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7721                                 else
7722                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7723                         }
7724                         
7725                 }
7726
7727                 if (mspecs [i + 1]) {
7728                         MonoReflectionMarshalAsAttribute* mobj;
7729                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7730                         if (!mobj)
7731                                 goto leave;
7732                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7733                 }
7734                 
7735                 mono_array_setref (res, i, param);
7736         }
7737
7738 leave:
7739         g_free (names);
7740         g_free (blobs);
7741         g_free (types);
7742         g_free (type);
7743
7744         if (sig) {
7745                 for (i = sig->param_count; i >= 0; i--) {
7746                         if (mspecs [i])
7747                                 mono_metadata_free_marshal_spec (mspecs [i]);
7748                 }
7749         }
7750         g_free (mspecs);
7751
7752         if (!is_ok (error))
7753                 return NULL;
7754         
7755         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7756 }
7757
7758 MonoArray*
7759 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7760 {
7761         MonoError error;
7762         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7763         mono_error_assert_ok (&error);
7764         return result;
7765 }
7766
7767 /*
7768  * mono_method_body_get_object:
7769  * @domain: an app domain
7770  * @method: a method
7771  *
7772  * Return an System.Reflection.MethodBody object representing the method @method.
7773  */
7774 MonoReflectionMethodBody*
7775 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7776 {
7777         MonoError error;
7778         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7779         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7780         return result;
7781 }
7782
7783 /**
7784  * mono_method_body_get_object_checked:
7785  * @domain: an app domain
7786  * @method: a method
7787  * @error: set on error
7788  *
7789  * Return an System.Reflection.MethodBody object representing the
7790  * method @method.  On failure, returns NULL and sets @error.
7791  */
7792 MonoReflectionMethodBody*
7793 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7794 {
7795         MonoReflectionMethodBody *ret;
7796         MonoMethodHeader *header;
7797         MonoImage *image;
7798         MonoReflectionType *rt;
7799         guint32 method_rva, local_var_sig_token;
7800         char *ptr;
7801         unsigned char format, flags;
7802         int i;
7803
7804         mono_error_init (error);
7805
7806         /* for compatibility with .net */
7807         if (method_is_dynamic (method)) {
7808                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7809                 return NULL;
7810         }
7811
7812         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7813
7814         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7815                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7816             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7817                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7818             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7819                 return NULL;
7820
7821         image = method->klass->image;
7822         header = mono_method_get_header_checked (method, error);
7823         return_val_if_nok (error, NULL);
7824
7825         if (!image_is_dynamic (image)) {
7826                 /* Obtain local vars signature token */
7827                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7828                 ptr = mono_image_rva_map (image, method_rva);
7829                 flags = *(const unsigned char *) ptr;
7830                 format = flags & METHOD_HEADER_FORMAT_MASK;
7831                 switch (format){
7832                 case METHOD_HEADER_TINY_FORMAT:
7833                         local_var_sig_token = 0;
7834                         break;
7835                 case METHOD_HEADER_FAT_FORMAT:
7836                         ptr += 2;
7837                         ptr += 2;
7838                         ptr += 4;
7839                         local_var_sig_token = read32 (ptr);
7840                         break;
7841                 default:
7842                         g_assert_not_reached ();
7843                 }
7844         } else
7845                 local_var_sig_token = 0; //FIXME
7846
7847         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7848         if (!is_ok (error))
7849                 goto fail;
7850
7851         ret->init_locals = header->init_locals;
7852         ret->max_stack = header->max_stack;
7853         ret->local_var_sig_token = local_var_sig_token;
7854         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7855         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7856
7857         /* Locals */
7858         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7859         for (i = 0; i < header->num_locals; ++i) {
7860                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7861                 if (!is_ok (error))
7862                         goto fail;
7863
7864                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7865                 if (!is_ok (error))
7866                         goto fail;
7867
7868                 MONO_OBJECT_SETREF (info, local_type, rt);
7869
7870                 info->is_pinned = header->locals [i]->pinned;
7871                 info->local_index = i;
7872                 mono_array_setref (ret->locals, i, info);
7873         }
7874
7875         /* Exceptions */
7876         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7877         for (i = 0; i < header->num_clauses; ++i) {
7878                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7879                 if (!is_ok (error))
7880                         goto fail;
7881                 MonoExceptionClause *clause = &header->clauses [i];
7882
7883                 info->flags = clause->flags;
7884                 info->try_offset = clause->try_offset;
7885                 info->try_length = clause->try_len;
7886                 info->handler_offset = clause->handler_offset;
7887                 info->handler_length = clause->handler_len;
7888                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7889                         info->filter_offset = clause->data.filter_offset;
7890                 else if (clause->data.catch_class) {
7891                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7892                         if (!is_ok (error))
7893                                 goto fail;
7894
7895                         MONO_OBJECT_SETREF (info, catch_type, rt);
7896                 }
7897
7898                 mono_array_setref (ret->clauses, i, info);
7899         }
7900
7901         mono_metadata_free_mh (header);
7902         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7903         return ret;
7904
7905 fail:
7906         mono_metadata_free_mh (header);
7907         return NULL;
7908 }
7909
7910 /**
7911  * mono_get_dbnull_object:
7912  * @domain: Domain where the object lives
7913  *
7914  * Returns the System.DBNull.Value singleton object
7915  *
7916  * Used as the value for ParameterInfo.DefaultValue 
7917  */
7918 MonoObject *
7919 mono_get_dbnull_object (MonoDomain *domain)
7920 {
7921         MonoError error;
7922         MonoObject *obj;
7923         static MonoClassField *dbnull_value_field = NULL;
7924         
7925         if (!dbnull_value_field) {
7926                 MonoClass *dbnull_klass;
7927                 dbnull_klass = mono_class_get_dbnull_class ();
7928                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7929                 g_assert (dbnull_value_field);
7930         }
7931         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7932         mono_error_assert_ok (&error);
7933         return obj;
7934 }
7935
7936 static void
7937 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7938 {
7939         guint32 param_index, i, lastp, crow = 0;
7940         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7941         gint32 idx;
7942
7943         MonoClass *klass = method->klass;
7944         MonoImage *image = klass->image;
7945         MonoMethodSignature *methodsig = mono_method_signature (method);
7946
7947         MonoTableInfo *constt;
7948         MonoTableInfo *methodt;
7949         MonoTableInfo *paramt;
7950
7951         if (!methodsig->param_count)
7952                 return;
7953
7954         mono_class_init (klass);
7955
7956         if (image_is_dynamic (klass->image)) {
7957                 MonoReflectionMethodAux *aux;
7958                 if (method->is_inflated)
7959                         method = ((MonoMethodInflated*)method)->declaring;
7960                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7961                 if (aux && aux->param_defaults) {
7962                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7963                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7964                 }
7965                 return;
7966         }
7967
7968         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7969         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7970         constt = &image->tables [MONO_TABLE_CONSTANT];
7971
7972         idx = mono_method_get_index (method) - 1;
7973         g_assert (idx != -1);
7974
7975         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7976         if (idx + 1 < methodt->rows)
7977                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7978         else
7979                 lastp = paramt->rows + 1;
7980
7981         for (i = param_index; i < lastp; ++i) {
7982                 guint32 paramseq;
7983
7984                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7985                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7986
7987                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7988                         continue;
7989
7990                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7991                 if (!crow) {
7992                         continue;
7993                 }
7994         
7995                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7996                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7997                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7998         }
7999
8000         return;
8001 }
8002
8003 MonoObject *
8004 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8005 {
8006         void *retval;
8007         MonoClass *klass;
8008         MonoObject *object;
8009         MonoType *basetype = type;
8010
8011         mono_error_init (error);
8012
8013         if (!blob)
8014                 return NULL;
8015         
8016         klass = mono_class_from_mono_type (type);
8017         if (klass->valuetype) {
8018                 object = mono_object_new_checked (domain, klass, error);
8019                 return_val_if_nok (error, NULL);
8020                 retval = ((gchar *) object + sizeof (MonoObject));
8021                 if (klass->enumtype)
8022                         basetype = mono_class_enum_basetype (klass);
8023         } else {
8024                 retval = &object;
8025         }
8026                         
8027         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
8028                 return object;
8029         else
8030                 return NULL;
8031 }
8032
8033 static int
8034 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8035         int found_sep;
8036         char *s;
8037         gboolean quoted = FALSE;
8038
8039         memset (assembly, 0, sizeof (MonoAssemblyName));
8040         assembly->culture = "";
8041         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8042
8043         if (*p == '"') {
8044                 quoted = TRUE;
8045                 p++;
8046         }
8047         assembly->name = p;
8048         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8049                 p++;
8050         if (quoted) {
8051                 if (*p != '"')
8052                         return 1;
8053                 *p = 0;
8054                 p++;
8055         }
8056         if (*p != ',')
8057                 return 1;
8058         *p = 0;
8059         /* Remove trailing whitespace */
8060         s = p - 1;
8061         while (*s && g_ascii_isspace (*s))
8062                 *s-- = 0;
8063         p ++;
8064         while (g_ascii_isspace (*p))
8065                 p++;
8066         while (*p) {
8067                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8068                         p += 8;
8069                         assembly->major = strtoul (p, &s, 10);
8070                         if (s == p || *s != '.')
8071                                 return 1;
8072                         p = ++s;
8073                         assembly->minor = strtoul (p, &s, 10);
8074                         if (s == p || *s != '.')
8075                                 return 1;
8076                         p = ++s;
8077                         assembly->build = strtoul (p, &s, 10);
8078                         if (s == p || *s != '.')
8079                                 return 1;
8080                         p = ++s;
8081                         assembly->revision = strtoul (p, &s, 10);
8082                         if (s == p)
8083                                 return 1;
8084                         p = s;
8085                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8086                         p += 8;
8087                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8088                                 assembly->culture = "";
8089                                 p += 7;
8090                         } else {
8091                                 assembly->culture = p;
8092                                 while (*p && *p != ',') {
8093                                         p++;
8094                                 }
8095                         }
8096                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8097                         p += 15;
8098                         if (strncmp (p, "null", 4) == 0) {
8099                                 p += 4;
8100                         } else {
8101                                 int len;
8102                                 gchar *start = p;
8103                                 while (*p && *p != ',') {
8104                                         p++;
8105                                 }
8106                                 len = (p - start + 1);
8107                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8108                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8109                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8110                         }
8111                 } else {
8112                         while (*p && *p != ',')
8113                                 p++;
8114                 }
8115                 found_sep = 0;
8116                 while (g_ascii_isspace (*p) || *p == ',') {
8117                         *p++ = 0;
8118                         found_sep = 1;
8119                         continue;
8120                 }
8121                 /* failed */
8122                 if (!found_sep)
8123                         return 1;
8124         }
8125
8126         return 0;
8127 }
8128
8129 /*
8130  * mono_reflection_parse_type:
8131  * @name: type name
8132  *
8133  * Parse a type name as accepted by the GetType () method and output the info
8134  * extracted in the info structure.
8135  * the name param will be mangled, so, make a copy before passing it to this function.
8136  * The fields in info will be valid until the memory pointed to by name is valid.
8137  *
8138  * See also mono_type_get_name () below.
8139  *
8140  * Returns: 0 on parse error.
8141  */
8142 static int
8143 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8144                              MonoTypeNameParse *info)
8145 {
8146         char *start, *p, *w, *last_point, *startn;
8147         int in_modifiers = 0;
8148         int isbyref = 0, rank = 0, isptr = 0;
8149
8150         start = p = w = name;
8151
8152         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8153         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8154         info->name = info->name_space = NULL;
8155         info->nested = NULL;
8156         info->modifiers = NULL;
8157         info->type_arguments = NULL;
8158
8159         /* last_point separates the namespace from the name */
8160         last_point = NULL;
8161         /* Skips spaces */
8162         while (*p == ' ') p++, start++, w++, name++;
8163
8164         while (*p) {
8165                 switch (*p) {
8166                 case '+':
8167                         *p = 0; /* NULL terminate the name */
8168                         startn = p + 1;
8169                         info->nested = g_list_append (info->nested, startn);
8170                         /* we have parsed the nesting namespace + name */
8171                         if (info->name)
8172                                 break;
8173                         if (last_point) {
8174                                 info->name_space = start;
8175                                 *last_point = 0;
8176                                 info->name = last_point + 1;
8177                         } else {
8178                                 info->name_space = (char *)"";
8179                                 info->name = start;
8180                         }
8181                         break;
8182                 case '.':
8183                         last_point = p;
8184                         break;
8185                 case '\\':
8186                         ++p;
8187                         break;
8188                 case '&':
8189                 case '*':
8190                 case '[':
8191                 case ',':
8192                 case ']':
8193                         in_modifiers = 1;
8194                         break;
8195                 default:
8196                         break;
8197                 }
8198                 if (in_modifiers)
8199                         break;
8200                 // *w++ = *p++;
8201                 p++;
8202         }
8203         
8204         if (!info->name) {
8205                 if (last_point) {
8206                         info->name_space = start;
8207                         *last_point = 0;
8208                         info->name = last_point + 1;
8209                 } else {
8210                         info->name_space = (char *)"";
8211                         info->name = start;
8212                 }
8213         }
8214         while (*p) {
8215                 switch (*p) {
8216                 case '&':
8217                         if (isbyref) /* only one level allowed by the spec */
8218                                 return 0;
8219                         isbyref = 1;
8220                         isptr = 0;
8221                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8222                         *p++ = 0;
8223                         break;
8224                 case '*':
8225                         if (isbyref) /* pointer to ref not okay */
8226                                 return 0;
8227                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8228                         isptr = 1;
8229                         *p++ = 0;
8230                         break;
8231                 case '[':
8232                         if (isbyref) /* array of ref and generic ref are not okay */
8233                                 return 0;
8234                         //Decide if it's an array of a generic argument list
8235                         *p++ = 0;
8236
8237                         if (!*p) //XXX test
8238                                 return 0;
8239                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8240                                 isptr = 0;
8241                                 rank = 1;
8242                                 while (*p) {
8243                                         if (*p == ']')
8244                                                 break;
8245                                         if (*p == ',')
8246                                                 rank++;
8247                                         else if (*p == '*') /* '*' means unknown lower bound */
8248                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8249                                         else
8250                                                 return 0;
8251                                         ++p;
8252                                 }
8253                                 if (*p++ != ']')
8254                                         return 0;
8255                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8256                         } else {
8257                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8258                                         return 0;
8259                                 isptr = 0;
8260                                 info->type_arguments = g_ptr_array_new ();
8261                                 while (*p) {
8262                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8263                                         gboolean fqname = FALSE;
8264
8265                                         g_ptr_array_add (info->type_arguments, subinfo);
8266
8267                                         while (*p == ' ') p++;
8268                                         if (*p == '[') {
8269                                                 p++;
8270                                                 fqname = TRUE;
8271                                         }
8272
8273                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8274                                                 return 0;
8275
8276                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8277                                         if (fqname && (*p != ']')) {
8278                                                 char *aname;
8279
8280                                                 if (*p != ',')
8281                                                         return 0;
8282                                                 *p++ = 0;
8283
8284                                                 aname = p;
8285                                                 while (*p && (*p != ']'))
8286                                                         p++;
8287
8288                                                 if (*p != ']')
8289                                                         return 0;
8290
8291                                                 *p++ = 0;
8292                                                 while (*aname) {
8293                                                         if (g_ascii_isspace (*aname)) {
8294                                                                 ++aname;
8295                                                                 continue;
8296                                                         }
8297                                                         break;
8298                                                 }
8299                                                 if (!*aname ||
8300                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8301                                                         return 0;
8302                                         } else if (fqname && (*p == ']')) {
8303                                                 *p++ = 0;
8304                                         }
8305                                         if (*p == ']') {
8306                                                 *p++ = 0;
8307                                                 break;
8308                                         } else if (!*p) {
8309                                                 return 0;
8310                                         }
8311                                         *p++ = 0;
8312                                 }
8313                         }
8314                         break;
8315                 case ']':
8316                         if (is_recursed)
8317                                 goto end;
8318                         return 0;
8319                 case ',':
8320                         if (is_recursed)
8321                                 goto end;
8322                         *p++ = 0;
8323                         while (*p) {
8324                                 if (g_ascii_isspace (*p)) {
8325                                         ++p;
8326                                         continue;
8327                                 }
8328                                 break;
8329                         }
8330                         if (!*p)
8331                                 return 0; /* missing assembly name */
8332                         if (!assembly_name_to_aname (&info->assembly, p))
8333                                 return 0;
8334                         break;
8335                 default:
8336                         return 0;
8337                 }
8338                 if (info->assembly.name)
8339                         break;
8340         }
8341         // *w = 0; /* terminate class name */
8342  end:
8343         if (!info->name || !*info->name)
8344                 return 0;
8345         if (endptr)
8346                 *endptr = p;
8347         /* add other consistency checks */
8348         return 1;
8349 }
8350
8351
8352 /**
8353  * mono_identifier_unescape_type_name_chars:
8354  * @identifier: the display name of a mono type
8355  *
8356  * Returns:
8357  *  The name in internal form, that is without escaping backslashes.
8358  *
8359  *  The string is modified in place!
8360  */
8361 char*
8362 mono_identifier_unescape_type_name_chars(char* identifier)
8363 {
8364         char *w, *r;
8365         if (!identifier)
8366                 return NULL;
8367         for (w = r = identifier; *r != 0; r++)
8368         {
8369                 char c = *r;
8370                 if (c == '\\') {
8371                         r++;
8372                         if (*r == 0)
8373                                 break;
8374                         c = *r;
8375                 }
8376                 *w = c;
8377                 w++;
8378         }
8379         if (w != r)
8380                 *w = 0;
8381         return identifier;
8382 }
8383
8384 void
8385 mono_identifier_unescape_info (MonoTypeNameParse* info);
8386
8387 static void
8388 unescape_each_type_argument(void* data, void* user_data)
8389 {
8390         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8391         mono_identifier_unescape_info (info);
8392 }
8393
8394 static void
8395 unescape_each_nested_name (void* data, void* user_data)
8396 {
8397         char* nested_name = (char*) data;
8398         mono_identifier_unescape_type_name_chars(nested_name);
8399 }
8400
8401 /**
8402  * mono_identifier_unescape_info:
8403  *
8404  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8405  *
8406  * Returns: nothing.
8407  *
8408  * Destructively updates the info by unescaping the identifiers that
8409  * comprise the type namespace, name, nested types (if any) and
8410  * generic type arguments (if any).
8411  *
8412  * The resulting info has the names in internal form.
8413  *
8414  */
8415 void
8416 mono_identifier_unescape_info (MonoTypeNameParse *info)
8417 {
8418         if (!info)
8419                 return;
8420         mono_identifier_unescape_type_name_chars(info->name_space);
8421         mono_identifier_unescape_type_name_chars(info->name);
8422         // but don't escape info->assembly
8423         if (info->type_arguments)
8424                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8425         if (info->nested)
8426                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8427 }
8428
8429 int
8430 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8431 {
8432         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8433         if (ok) {
8434                 mono_identifier_unescape_info (info);
8435         }
8436         return ok;
8437 }
8438
8439 static MonoType*
8440 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8441 {
8442         gboolean type_resolve = FALSE;
8443         MonoType *type;
8444         MonoImage *rootimage = image;
8445
8446         mono_error_init (error);
8447
8448         if (info->assembly.name) {
8449                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8450                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8451                         /* 
8452                          * This could happen in the AOT compiler case when the search hook is not
8453                          * installed.
8454                          */
8455                         assembly = image->assembly;
8456                 if (!assembly) {
8457                         /* then we must load the assembly ourselve - see #60439 */
8458                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8459                         if (!assembly)
8460                                 return NULL;
8461                 }
8462                 image = assembly->image;
8463         } else if (!image) {
8464                 image = mono_defaults.corlib;
8465         }
8466
8467         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8468         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8469                 mono_error_cleanup (error);
8470                 image = mono_defaults.corlib;
8471                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8472         }
8473
8474         return type;
8475 }
8476
8477 /**
8478  * mono_reflection_get_type_internal:
8479  *
8480  * Returns: may return NULL on success, sets error on failure.
8481  */
8482 static MonoType*
8483 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8484 {
8485         MonoClass *klass;
8486         GList *mod;
8487         int modval;
8488         gboolean bounded = FALSE;
8489         
8490         mono_error_init (error);
8491         if (!image)
8492                 image = mono_defaults.corlib;
8493
8494         if (!rootimage)
8495                 rootimage = mono_defaults.corlib;
8496
8497         if (ignorecase)
8498                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8499         else
8500                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8501
8502         if (!klass)
8503                 return NULL;
8504
8505         for (mod = info->nested; mod; mod = mod->next) {
8506                 gpointer iter = NULL;
8507                 MonoClass *parent;
8508
8509                 parent = klass;
8510                 mono_class_init (parent);
8511
8512                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8513                         char *lastp;
8514                         char *nested_name, *nested_nspace;
8515                         gboolean match = TRUE;
8516
8517                         lastp = strrchr ((const char *)mod->data, '.');
8518                         if (lastp) {
8519                                 /* Nested classes can have namespaces */
8520                                 int nspace_len;
8521
8522                                 nested_name = g_strdup (lastp + 1);
8523                                 nspace_len = lastp - (char*)mod->data;
8524                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8525                                 memcpy (nested_nspace, mod->data, nspace_len);
8526                                 nested_nspace [nspace_len] = '\0';
8527
8528                         } else {
8529                                 nested_name = (char *)mod->data;
8530                                 nested_nspace = NULL;
8531                         }
8532
8533                         if (nested_nspace) {
8534                                 if (ignorecase) {
8535                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8536                                                 match = FALSE;
8537                                 } else {
8538                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8539                                                 match = FALSE;
8540                                 }
8541                         }
8542                         if (match) {
8543                                 if (ignorecase) {
8544                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8545                                                 match = FALSE;
8546                                 } else {
8547                                         if (strcmp (klass->name, nested_name) != 0)
8548                                                 match = FALSE;
8549                                 }
8550                         }
8551                         if (lastp) {
8552                                 g_free (nested_name);
8553                                 g_free (nested_nspace);
8554                         }
8555                         if (match)
8556                                 break;
8557                 }
8558
8559                 if (!klass)
8560                         break;
8561         }
8562         if (!klass)
8563                 return NULL;
8564
8565         if (info->type_arguments) {
8566                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8567                 MonoReflectionType *the_type;
8568                 MonoType *instance;
8569                 int i;
8570
8571                 for (i = 0; i < info->type_arguments->len; i++) {
8572                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8573
8574                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8575                         if (!type_args [i]) {
8576                                 g_free (type_args);
8577                                 return NULL;
8578                         }
8579                 }
8580
8581                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8582                 if (!the_type)
8583                         return NULL;
8584
8585                 instance = mono_reflection_bind_generic_parameters (
8586                         the_type, info->type_arguments->len, type_args, error);
8587
8588                 g_free (type_args);
8589                 if (!instance)
8590                         return NULL;
8591
8592                 klass = mono_class_from_mono_type (instance);
8593         }
8594
8595         for (mod = info->modifiers; mod; mod = mod->next) {
8596                 modval = GPOINTER_TO_UINT (mod->data);
8597                 if (!modval) { /* byref: must be last modifier */
8598                         return &klass->this_arg;
8599                 } else if (modval == -1) {
8600                         klass = mono_ptr_class_get (&klass->byval_arg);
8601                 } else if (modval == -2) {
8602                         bounded = TRUE;
8603                 } else { /* array rank */
8604                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8605                 }
8606         }
8607
8608         return &klass->byval_arg;
8609 }
8610
8611 /*
8612  * mono_reflection_get_type:
8613  * @image: a metadata context
8614  * @info: type description structure
8615  * @ignorecase: flag for case-insensitive string compares
8616  * @type_resolve: whenever type resolve was already tried
8617  *
8618  * Build a MonoType from the type description in @info.
8619  * 
8620  */
8621
8622 MonoType*
8623 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8624         MonoError error;
8625         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8626         mono_error_cleanup (&error);
8627         return result;
8628 }
8629
8630 /**
8631  * mono_reflection_get_type_checked:
8632  * @image: a metadata context
8633  * @info: type description structure
8634  * @ignorecase: flag for case-insensitive string compares
8635  * @type_resolve: whenever type resolve was already tried
8636  * @error: set on error.
8637  *
8638  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8639  *
8640  */
8641 MonoType*
8642 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8643         mono_error_init (error);
8644         return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8645 }
8646
8647
8648 static MonoType*
8649 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8650 {
8651         MonoReflectionAssemblyBuilder *abuilder;
8652         MonoType *type;
8653         int i;
8654
8655         mono_error_init (error);
8656         g_assert (assembly_is_dynamic (assembly));
8657         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8658         if (!abuilder)
8659                 return NULL;
8660
8661         /* Enumerate all modules */
8662
8663         type = NULL;
8664         if (abuilder->modules) {
8665                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8666                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8667                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8668                         if (type)
8669                                 break;
8670                         if (!mono_error_ok (error))
8671                                 return NULL;
8672                 }
8673         }
8674
8675         if (!type && abuilder->loaded_modules) {
8676                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8677                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8678                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8679                         if (type)
8680                                 break;
8681                         if (!mono_error_ok (error))
8682                                 return NULL;
8683                 }
8684         }
8685
8686         return type;
8687 }
8688         
8689 MonoType*
8690 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8691 {
8692         MonoType *type;
8693         MonoReflectionAssembly *assembly;
8694         GString *fullName;
8695         GList *mod;
8696
8697         mono_error_init (error);
8698
8699         if (image && image_is_dynamic (image))
8700                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8701         else {
8702                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8703         }
8704         return_val_if_nok (error, NULL);
8705
8706         if (type)
8707                 return type;
8708         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8709                 return NULL;
8710
8711         if (type_resolve) {
8712                 if (*type_resolve) 
8713                         return NULL;
8714                 else
8715                         *type_resolve = TRUE;
8716         }
8717         
8718         /* Reconstruct the type name */
8719         fullName = g_string_new ("");
8720         if (info->name_space && (info->name_space [0] != '\0'))
8721                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8722         else
8723                 g_string_printf (fullName, "%s", info->name);
8724         for (mod = info->nested; mod; mod = mod->next)
8725                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8726
8727         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8728         if (!is_ok (error)) {
8729                 g_string_free (fullName, TRUE);
8730                 return NULL;
8731         }
8732
8733         if (assembly) {
8734                 if (assembly_is_dynamic (assembly->assembly))
8735                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8736                                                                           info, ignorecase, error);
8737                 else
8738                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8739                                                                   info, ignorecase, error);
8740         }
8741         g_string_free (fullName, TRUE);
8742         return_val_if_nok (error, NULL);
8743         return type;
8744 }
8745
8746 void
8747 mono_reflection_free_type_info (MonoTypeNameParse *info)
8748 {
8749         g_list_free (info->modifiers);
8750         g_list_free (info->nested);
8751
8752         if (info->type_arguments) {
8753                 int i;
8754
8755                 for (i = 0; i < info->type_arguments->len; i++) {
8756                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8757
8758                         mono_reflection_free_type_info (subinfo);
8759                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8760                         g_free (subinfo);
8761                 }
8762
8763                 g_ptr_array_free (info->type_arguments, TRUE);
8764         }
8765 }
8766
8767 /*
8768  * mono_reflection_type_from_name:
8769  * @name: type name.
8770  * @image: a metadata context (can be NULL).
8771  *
8772  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8773  * it defaults to get the type from @image or, if @image is NULL or loading
8774  * from it fails, uses corlib.
8775  * 
8776  */
8777 MonoType*
8778 mono_reflection_type_from_name (char *name, MonoImage *image)
8779 {
8780         MonoError error;
8781         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8782         mono_error_cleanup (&error);
8783         return result;
8784 }
8785
8786 /**
8787  * mono_reflection_type_from_name_checked:
8788  * @name: type name.
8789  * @image: a metadata context (can be NULL).
8790  * @error: set on errror.
8791  *
8792  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8793  * it defaults to get the type from @image or, if @image is NULL or loading
8794  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8795  * 
8796  */
8797 MonoType*
8798 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8799 {
8800         MonoType *type = NULL;
8801         MonoTypeNameParse info;
8802         char *tmp;
8803
8804         mono_error_init (error);
8805         /* Make a copy since parse_type modifies its argument */
8806         tmp = g_strdup (name);
8807         
8808         /*g_print ("requested type %s\n", str);*/
8809         if (mono_reflection_parse_type (tmp, &info)) {
8810                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8811                 if (!is_ok (error)) {
8812                         g_free (tmp);
8813                         mono_reflection_free_type_info (&info);
8814                         return NULL;
8815                 }
8816         }
8817
8818         g_free (tmp);
8819         mono_reflection_free_type_info (&info);
8820         return type;
8821 }
8822
8823 /*
8824  * mono_reflection_get_token:
8825  *
8826  *   Return the metadata token of OBJ which should be an object
8827  * representing a metadata element.
8828  */
8829 guint32
8830 mono_reflection_get_token (MonoObject *obj)
8831 {
8832         MonoError error;
8833         guint32 result = mono_reflection_get_token_checked (obj, &error);
8834         mono_error_assert_ok (&error);
8835         return result;
8836 }
8837
8838 /**
8839  * mono_reflection_get_token_checked:
8840  * @obj: the object
8841  * @error: set on error
8842  *
8843  *   Return the metadata token of @obj which should be an object
8844  * representing a metadata element.  On failure sets @error.
8845  */
8846 guint32
8847 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8848 {
8849         MonoClass *klass;
8850         guint32 token = 0;
8851
8852         mono_error_init (error);
8853
8854         klass = obj->vtable->klass;
8855
8856         if (strcmp (klass->name, "MethodBuilder") == 0) {
8857                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8858
8859                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8860         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8861                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8862
8863                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8864         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8865                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8866
8867                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8868         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8869                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8870                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8871         } else if (strcmp (klass->name, "MonoType") == 0) {
8872                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8873                 return_val_if_nok (error, 0);
8874                 MonoClass *mc = mono_class_from_mono_type (type);
8875                 if (!mono_class_init (mc)) {
8876                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8877                         return 0;
8878                 }
8879
8880                 token = mc->type_token;
8881         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8882                    strcmp (klass->name, "MonoMethod") == 0 ||
8883                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8884                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8885                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8886                 if (m->method->is_inflated) {
8887                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8888                         return inflated->declaring->token;
8889                 } else {
8890                         token = m->method->token;
8891                 }
8892         } else if (strcmp (klass->name, "MonoField") == 0) {
8893                 MonoReflectionField *f = (MonoReflectionField*)obj;
8894
8895                 if (is_field_on_inst (f->field)) {
8896                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8897
8898                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8899                                 int field_index = f->field - dgclass->fields;
8900                                 MonoObject *obj;
8901
8902                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8903                                 obj = dgclass->field_objects [field_index];
8904                                 return mono_reflection_get_token_checked (obj, error);
8905                         }
8906                 }
8907                 token = mono_class_get_field_token (f->field);
8908         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8909                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8910
8911                 token = mono_class_get_property_token (p->property);
8912         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8913                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8914
8915                 token = mono_class_get_event_token (p->event);
8916         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8917                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8918                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8919                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8920
8921                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8922         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8923                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8924
8925                 token = m->token;
8926         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8927                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8928         } else {
8929                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8930                                                 klass->name_space, klass->name);
8931                 return 0;
8932         }
8933
8934         return token;
8935 }
8936
8937 static MonoClass*
8938 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8939 {
8940         char *n;
8941         MonoType *t;
8942         int slen = mono_metadata_decode_value (p, &p);
8943
8944         mono_error_init (error);
8945
8946         n = (char *)g_memdup (p, slen + 1);
8947         n [slen] = 0;
8948         t = mono_reflection_type_from_name_checked (n, image, error);
8949         if (!t) {
8950                 char *msg = g_strdup (mono_error_get_message (error));
8951                 mono_error_cleanup (error);
8952                 /* We don't free n, it's consumed by mono_error */
8953                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8954                 g_free (msg);
8955                 return NULL;
8956         }
8957         g_free (n);
8958         p += slen;
8959         *end = p;
8960         return mono_class_from_mono_type (t);
8961 }
8962
8963 static void*
8964 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8965 {
8966         int slen, type = t->type;
8967         MonoClass *tklass = t->data.klass;
8968
8969         mono_error_init (error);
8970
8971 handle_enum:
8972         switch (type) {
8973         case MONO_TYPE_U1:
8974         case MONO_TYPE_I1:
8975         case MONO_TYPE_BOOLEAN: {
8976                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8977                 *bval = *p;
8978                 *end = p + 1;
8979                 return bval;
8980         }
8981         case MONO_TYPE_CHAR:
8982         case MONO_TYPE_U2:
8983         case MONO_TYPE_I2: {
8984                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8985                 *val = read16 (p);
8986                 *end = p + 2;
8987                 return val;
8988         }
8989 #if SIZEOF_VOID_P == 4
8990         case MONO_TYPE_U:
8991         case MONO_TYPE_I:
8992 #endif
8993         case MONO_TYPE_R4:
8994         case MONO_TYPE_U4:
8995         case MONO_TYPE_I4: {
8996                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8997                 *val = read32 (p);
8998                 *end = p + 4;
8999                 return val;
9000         }
9001 #if SIZEOF_VOID_P == 8
9002         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9003         case MONO_TYPE_I:
9004 #endif
9005         case MONO_TYPE_U8:
9006         case MONO_TYPE_I8: {
9007                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9008                 *val = read64 (p);
9009                 *end = p + 8;
9010                 return val;
9011         }
9012         case MONO_TYPE_R8: {
9013                 double *val = (double *)g_malloc (sizeof (double));
9014                 readr8 (p, val);
9015                 *end = p + 8;
9016                 return val;
9017         }
9018         case MONO_TYPE_VALUETYPE:
9019                 if (t->data.klass->enumtype) {
9020                         type = mono_class_enum_basetype (t->data.klass)->type;
9021                         goto handle_enum;
9022                 } else {
9023                         MonoClass *k =  t->data.klass;
9024                         
9025                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9026                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9027                                 *val = read64 (p);
9028                                 *end = p + 8;
9029                                 return val;
9030                         }
9031                 }
9032                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9033                 break;
9034                 
9035         case MONO_TYPE_STRING:
9036                 if (*p == (char)0xFF) {
9037                         *end = p + 1;
9038                         return NULL;
9039                 }
9040                 slen = mono_metadata_decode_value (p, &p);
9041                 *end = p + slen;
9042                 return mono_string_new_len (mono_domain_get (), p, slen);
9043         case MONO_TYPE_CLASS: {
9044                 MonoReflectionType *rt;
9045                 char *n;
9046                 MonoType *t;
9047                 if (*p == (char)0xFF) {
9048                         *end = p + 1;
9049                         return NULL;
9050                 }
9051 handle_type:
9052                 slen = mono_metadata_decode_value (p, &p);
9053                 n = (char *)g_memdup (p, slen + 1);
9054                 n [slen] = 0;
9055                 t = mono_reflection_type_from_name_checked (n, image, error);
9056                 if (!t) {
9057                         char *msg = g_strdup (mono_error_get_message (error));
9058                         mono_error_cleanup (error);
9059                         /* We don't free n, it's consumed by mono_error */
9060                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9061                         g_free (msg);
9062                         return NULL;
9063                 }
9064                 g_free (n);
9065                 *end = p + slen;
9066
9067                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9068                 if (!mono_error_ok (error))
9069                         return NULL;
9070
9071                 return rt;
9072         }
9073         case MONO_TYPE_OBJECT: {
9074                 char subt = *p++;
9075                 MonoObject *obj;
9076                 MonoClass *subc = NULL;
9077                 void *val;
9078
9079                 if (subt == 0x50) {
9080                         goto handle_type;
9081                 } else if (subt == 0x0E) {
9082                         type = MONO_TYPE_STRING;
9083                         goto handle_enum;
9084                 } else if (subt == 0x1D) {
9085                         MonoType simple_type = {{0}};
9086                         int etype = *p;
9087                         p ++;
9088
9089                         type = MONO_TYPE_SZARRAY;
9090                         if (etype == 0x50) {
9091                                 tklass = mono_defaults.systemtype_class;
9092                         } else if (etype == 0x55) {
9093                                 tklass = load_cattr_enum_type (image, p, &p, error);
9094                                 if (!mono_error_ok (error))
9095                                         return NULL;
9096                         } else {
9097                                 if (etype == 0x51)
9098                                         /* See Partition II, Appendix B3 */
9099                                         etype = MONO_TYPE_OBJECT;
9100                                 simple_type.type = (MonoTypeEnum)etype;
9101                                 tklass = mono_class_from_mono_type (&simple_type);
9102                         }
9103                         goto handle_enum;
9104                 } else if (subt == 0x55) {
9105                         char *n;
9106                         MonoType *t;
9107                         slen = mono_metadata_decode_value (p, &p);
9108                         n = (char *)g_memdup (p, slen + 1);
9109                         n [slen] = 0;
9110                         t = mono_reflection_type_from_name_checked (n, image, error);
9111                         if (!t) {
9112                                 char *msg = g_strdup (mono_error_get_message (error));
9113                                 mono_error_cleanup (error);
9114                                 /* We don't free n, it's consumed by mono_error */
9115                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9116                                 g_free (msg);
9117                                 return NULL;
9118                         }
9119                         g_free (n);
9120                         p += slen;
9121                         subc = mono_class_from_mono_type (t);
9122                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9123                         MonoType simple_type = {{0}};
9124                         simple_type.type = (MonoTypeEnum)subt;
9125                         subc = mono_class_from_mono_type (&simple_type);
9126                 } else {
9127                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9128                 }
9129                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9130                 obj = NULL;
9131                 if (mono_error_ok (error)) {
9132                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9133                         g_assert (!subc->has_references);
9134                         if (mono_error_ok (error))
9135                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9136                 }
9137
9138                 g_free (val);
9139                 return obj;
9140         }
9141         case MONO_TYPE_SZARRAY: {
9142                 MonoArray *arr;
9143                 guint32 i, alen, basetype;
9144                 alen = read32 (p);
9145                 p += 4;
9146                 if (alen == 0xffffffff) {
9147                         *end = p;
9148                         return NULL;
9149                 }
9150                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9151                 basetype = tklass->byval_arg.type;
9152                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9153                         basetype = mono_class_enum_basetype (tklass)->type;
9154                 switch (basetype)
9155                 {
9156                         case MONO_TYPE_U1:
9157                         case MONO_TYPE_I1:
9158                         case MONO_TYPE_BOOLEAN:
9159                                 for (i = 0; i < alen; i++) {
9160                                         MonoBoolean val = *p++;
9161                                         mono_array_set (arr, MonoBoolean, i, val);
9162                                 }
9163                                 break;
9164                         case MONO_TYPE_CHAR:
9165                         case MONO_TYPE_U2:
9166                         case MONO_TYPE_I2:
9167                                 for (i = 0; i < alen; i++) {
9168                                         guint16 val = read16 (p);
9169                                         mono_array_set (arr, guint16, i, val);
9170                                         p += 2;
9171                                 }
9172                                 break;
9173                         case MONO_TYPE_R4:
9174                         case MONO_TYPE_U4:
9175                         case MONO_TYPE_I4:
9176                                 for (i = 0; i < alen; i++) {
9177                                         guint32 val = read32 (p);
9178                                         mono_array_set (arr, guint32, i, val);
9179                                         p += 4;
9180                                 }
9181                                 break;
9182                         case MONO_TYPE_R8:
9183                                 for (i = 0; i < alen; i++) {
9184                                         double val;
9185                                         readr8 (p, &val);
9186                                         mono_array_set (arr, double, i, val);
9187                                         p += 8;
9188                                 }
9189                                 break;
9190                         case MONO_TYPE_U8:
9191                         case MONO_TYPE_I8:
9192                                 for (i = 0; i < alen; i++) {
9193                                         guint64 val = read64 (p);
9194                                         mono_array_set (arr, guint64, i, val);
9195                                         p += 8;
9196                                 }
9197                                 break;
9198                         case MONO_TYPE_CLASS:
9199                         case MONO_TYPE_OBJECT:
9200                         case MONO_TYPE_STRING:
9201                         case MONO_TYPE_SZARRAY:
9202                                 for (i = 0; i < alen; i++) {
9203                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9204                                         if (!mono_error_ok (error))
9205                                                 return NULL;
9206                                         mono_array_setref (arr, i, item);
9207                                 }
9208                                 break;
9209                         default:
9210                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9211                 }
9212                 *end=p;
9213                 return arr;
9214         }
9215         default:
9216                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9217         }
9218         return NULL;
9219 }
9220
9221 static MonoObject*
9222 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9223 {
9224         mono_error_init (error);
9225
9226         gboolean is_ref = type_is_reference (t);
9227
9228         void *val = load_cattr_value (image, t, p, end, error);
9229         if (!is_ok (error)) {
9230                 if (is_ref)
9231                         g_free (val);
9232                 return NULL;
9233         }
9234
9235         if (is_ref)
9236                 return (MonoObject*)val;
9237
9238         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9239         g_free (val);
9240         return boxed;
9241 }
9242
9243 static MonoObject*
9244 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9245 {
9246         static MonoMethod *ctor;
9247         MonoObject *retval;
9248         void *params [2], *unboxed;
9249
9250         mono_error_init (error);
9251
9252         if (!ctor)
9253                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9254         
9255         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9256         return_val_if_nok (error, NULL);
9257
9258         params [1] = val;
9259         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9260         return_val_if_nok (error, NULL);
9261         unboxed = mono_object_unbox (retval);
9262
9263         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9264         return_val_if_nok (error, NULL);
9265
9266         return retval;
9267 }
9268
9269 static MonoObject*
9270 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9271 {
9272         static MonoMethod *ctor;
9273         MonoObject *retval;
9274         void *unboxed, *params [2];
9275
9276         mono_error_init (error);
9277
9278         if (!ctor)
9279                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9280
9281         params [0] = minfo;
9282         params [1] = typedarg;
9283         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9284         return_val_if_nok (error, NULL);
9285
9286         unboxed = mono_object_unbox (retval);
9287
9288         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9289         return_val_if_nok (error, NULL);
9290
9291         return retval;
9292 }
9293
9294 static gboolean
9295 type_is_reference (MonoType *type)
9296 {
9297         switch (type->type) {
9298         case MONO_TYPE_BOOLEAN:
9299         case MONO_TYPE_CHAR:
9300         case MONO_TYPE_U:
9301         case MONO_TYPE_I:
9302         case MONO_TYPE_U1:
9303         case MONO_TYPE_I1:
9304         case MONO_TYPE_U2:
9305         case MONO_TYPE_I2:
9306         case MONO_TYPE_U4:
9307         case MONO_TYPE_I4:
9308         case MONO_TYPE_U8:
9309         case MONO_TYPE_I8:
9310         case MONO_TYPE_R8:
9311         case MONO_TYPE_R4:
9312         case MONO_TYPE_VALUETYPE:
9313                 return FALSE;
9314         default:
9315                 return TRUE;
9316         }
9317 }
9318
9319 static void
9320 free_param_data (MonoMethodSignature *sig, void **params) {
9321         int i;
9322         for (i = 0; i < sig->param_count; ++i) {
9323                 if (!type_is_reference (sig->params [i]))
9324                         g_free (params [i]);
9325         }
9326 }
9327
9328 /*
9329  * Find the field index in the metadata FieldDef table.
9330  */
9331 static guint32
9332 find_field_index (MonoClass *klass, MonoClassField *field) {
9333         int i;
9334
9335         for (i = 0; i < klass->field.count; ++i) {
9336                 if (field == &klass->fields [i])
9337                         return klass->field.first + 1 + i;
9338         }
9339         return 0;
9340 }
9341
9342 /*
9343  * Find the property index in the metadata Property table.
9344  */
9345 static guint32
9346 find_property_index (MonoClass *klass, MonoProperty *property) {
9347         int i;
9348
9349         for (i = 0; i < klass->ext->property.count; ++i) {
9350                 if (property == &klass->ext->properties [i])
9351                         return klass->ext->property.first + 1 + i;
9352         }
9353         return 0;
9354 }
9355
9356 /*
9357  * Find the event index in the metadata Event table.
9358  */
9359 static guint32
9360 find_event_index (MonoClass *klass, MonoEvent *event) {
9361         int i;
9362
9363         for (i = 0; i < klass->ext->event.count; ++i) {
9364                 if (event == &klass->ext->events [i])
9365                         return klass->ext->event.first + 1 + i;
9366         }
9367         return 0;
9368 }
9369
9370 static MonoObject*
9371 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9372 {
9373         const char *p = (const char*)data;
9374         const char *named;
9375         guint32 i, j, num_named;
9376         MonoObject *attr;
9377         void *params_buf [32];
9378         void **params = NULL;
9379         MonoMethodSignature *sig;
9380         MonoObject *exc = NULL;
9381
9382         mono_error_init (error);
9383
9384         mono_class_init (method->klass);
9385
9386         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9387                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9388                 return NULL;
9389         }
9390
9391         if (len == 0) {
9392                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9393                 if (!mono_error_ok (error)) return NULL;
9394
9395                 mono_runtime_invoke_checked (method, attr, NULL, error);
9396                 if (!mono_error_ok (error))
9397                         return NULL;
9398
9399                 return attr;
9400         }
9401
9402         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9403                 return NULL;
9404
9405         /*g_print ("got attr %s\n", method->klass->name);*/
9406
9407         sig = mono_method_signature (method);
9408         if (sig->param_count < 32) {
9409                 params = params_buf;
9410                 memset (params, 0, sizeof (void*) * sig->param_count);
9411         } else {
9412                 /* Allocate using GC so it gets GC tracking */
9413                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9414         }
9415
9416         /* skip prolog */
9417         p += 2;
9418         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9419                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9420                 if (!mono_error_ok (error))
9421                         goto fail;
9422         }
9423
9424         named = p;
9425         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9426         if (!mono_error_ok (error)) goto fail;
9427
9428         mono_runtime_try_invoke (method, attr, params, &exc, error);
9429         if (!mono_error_ok (error))
9430                 goto fail;
9431         if (exc)
9432                 goto fail;
9433
9434         num_named = read16 (named);
9435         named += 2;
9436         for (j = 0; j < num_named; j++) {
9437                 gint name_len;
9438                 char *name, named_type, data_type;
9439                 named_type = *named++;
9440                 data_type = *named++; /* type of data */
9441                 if (data_type == MONO_TYPE_SZARRAY)
9442                         data_type = *named++;
9443                 if (data_type == MONO_TYPE_ENUM) {
9444                         gint type_len;
9445                         char *type_name;
9446                         type_len = mono_metadata_decode_blob_size (named, &named);
9447                         type_name = (char *)g_malloc (type_len + 1);
9448                         memcpy (type_name, named, type_len);
9449                         type_name [type_len] = 0;
9450                         named += type_len;
9451                         /* FIXME: lookup the type and check type consistency */
9452                         g_free (type_name);
9453                 }
9454                 name_len = mono_metadata_decode_blob_size (named, &named);
9455                 name = (char *)g_malloc (name_len + 1);
9456                 memcpy (name, named, name_len);
9457                 name [name_len] = 0;
9458                 named += name_len;
9459                 if (named_type == 0x53) {
9460                         MonoClassField *field;
9461                         void *val;
9462
9463                         /* how this fail is a blackbox */
9464                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9465                         if (!field) {
9466                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9467                                 g_free (name);
9468                                 goto fail;
9469                         }
9470
9471                         val = load_cattr_value (image, field->type, named, &named, error);
9472                         if (!mono_error_ok (error)) {
9473                                 g_free (name);
9474                                 if (!type_is_reference (field->type))
9475                                         g_free (val);
9476                                 goto fail;
9477                         }
9478
9479                         mono_field_set_value (attr, field, val);
9480                         if (!type_is_reference (field->type))
9481                                 g_free (val);
9482                 } else if (named_type == 0x54) {
9483                         MonoProperty *prop;
9484                         void *pparams [1];
9485                         MonoType *prop_type;
9486
9487                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9488
9489                         if (!prop) {
9490                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9491                                 g_free (name);
9492                                 goto fail;
9493                         }
9494
9495                         if (!prop->set) {
9496                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9497                                 g_free (name);
9498                                 goto fail;
9499                         }
9500
9501                         /* can we have more that 1 arg in a custom attr named property? */
9502                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9503                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9504
9505                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9506                         if (!mono_error_ok (error)) {
9507                                 g_free (name);
9508                                 if (!type_is_reference (prop_type))
9509                                         g_free (pparams [0]);
9510                                 goto fail;
9511                         }
9512
9513
9514                         mono_property_set_value (prop, attr, pparams, NULL);
9515                         if (!type_is_reference (prop_type))
9516                                 g_free (pparams [0]);
9517                 }
9518                 g_free (name);
9519         }
9520
9521         free_param_data (method->signature, params);
9522         if (params != params_buf)
9523                 mono_gc_free_fixed (params);
9524
9525         return attr;
9526
9527 fail:
9528         free_param_data (method->signature, params);
9529         if (params != params_buf)
9530                 mono_gc_free_fixed (params);
9531         if (exc)
9532                 mono_raise_exception ((MonoException*)exc);
9533         return NULL;
9534 }
9535         
9536 /*
9537  * mono_reflection_create_custom_attr_data_args:
9538  *
9539  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9540  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9541  * NAMED_ARG_INFO will contain information about the named arguments.
9542  */
9543 void
9544 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)
9545 {
9546         MonoArray *typedargs, *namedargs;
9547         MonoClass *attrklass;
9548         MonoDomain *domain;
9549         const char *p = (const char*)data;
9550         const char *named;
9551         guint32 i, j, num_named;
9552         CattrNamedArg *arginfo = NULL;
9553
9554         *typed_args = NULL;
9555         *named_args = NULL;
9556         *named_arg_info = NULL;
9557
9558         mono_error_init (error);
9559
9560         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9561                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9562                 return;
9563         }
9564
9565         mono_class_init (method->klass);
9566         
9567         domain = mono_domain_get ();
9568
9569         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9570                 return;
9571
9572         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9573         
9574         /* skip prolog */
9575         p += 2;
9576         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9577                 MonoObject *obj;
9578
9579                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9580                 return_if_nok (error);
9581                 mono_array_setref (typedargs, i, obj);
9582         }
9583
9584         named = p;
9585         num_named = read16 (named);
9586         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9587         named += 2;
9588         attrklass = method->klass;
9589
9590         arginfo = g_new0 (CattrNamedArg, num_named);
9591         *named_arg_info = arginfo;
9592
9593         for (j = 0; j < num_named; j++) {
9594                 gint name_len;
9595                 char *name, named_type, data_type;
9596                 named_type = *named++;
9597                 data_type = *named++; /* type of data */
9598                 if (data_type == MONO_TYPE_SZARRAY)
9599                         data_type = *named++;
9600                 if (data_type == MONO_TYPE_ENUM) {
9601                         gint type_len;
9602                         char *type_name;
9603                         type_len = mono_metadata_decode_blob_size (named, &named);
9604                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9605                                 goto fail;
9606
9607                         type_name = (char *)g_malloc (type_len + 1);
9608                         memcpy (type_name, named, type_len);
9609                         type_name [type_len] = 0;
9610                         named += type_len;
9611                         /* FIXME: lookup the type and check type consistency */
9612                         g_free (type_name);
9613                 }
9614                 name_len = mono_metadata_decode_blob_size (named, &named);
9615                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9616                         goto fail;
9617                 name = (char *)g_malloc (name_len + 1);
9618                 memcpy (name, named, name_len);
9619                 name [name_len] = 0;
9620                 named += name_len;
9621                 if (named_type == 0x53) {
9622                         MonoObject *obj;
9623                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9624
9625                         if (!field) {
9626                                 g_free (name);
9627                                 goto fail;
9628                         }
9629
9630                         arginfo [j].type = field->type;
9631                         arginfo [j].field = field;
9632
9633                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9634                         if (!is_ok (error)) {
9635                                 g_free (name);
9636                                 return;
9637                         }
9638                         mono_array_setref (namedargs, j, obj);
9639
9640                 } else if (named_type == 0x54) {
9641                         MonoObject *obj;
9642                         MonoType *prop_type;
9643                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9644
9645                         if (!prop || !prop->set) {
9646                                 g_free (name);
9647                                 goto fail;
9648                         }
9649
9650                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9651                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9652
9653                         arginfo [j].type = prop_type;
9654                         arginfo [j].prop = prop;
9655
9656                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9657                         if (!is_ok (error)) {
9658                                 g_free (name);
9659                                 return;
9660                         }
9661                         mono_array_setref (namedargs, j, obj);
9662                 }
9663                 g_free (name);
9664         }
9665
9666         *typed_args = typedargs;
9667         *named_args = namedargs;
9668         return;
9669 fail:
9670         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9671         g_free (arginfo);
9672         *named_arg_info = NULL;
9673 }
9674
9675 void
9676 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9677 {
9678         MonoDomain *domain;
9679         MonoArray *typedargs, *namedargs;
9680         MonoImage *image;
9681         MonoMethod *method;
9682         CattrNamedArg *arginfo = NULL;
9683         MonoError error;
9684         int i;
9685
9686         mono_error_init (&error);
9687
9688         *ctor_args = NULL;
9689         *named_args = NULL;
9690
9691         if (len == 0)
9692                 return;
9693
9694         image = assembly->assembly->image;
9695         method = ref_method->method;
9696         domain = mono_object_domain (ref_method);
9697
9698         if (!mono_class_init (method->klass))
9699                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9700
9701         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9702         if (!mono_error_ok (&error))
9703                 goto leave;
9704
9705         if (mono_loader_get_last_error ()) {
9706                 mono_error_set_from_loader_error (&error);
9707                 goto leave;
9708         }
9709
9710         if (!typedargs || !namedargs)
9711                 goto leave;
9712
9713         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9714                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9715                 MonoObject *typedarg;
9716
9717                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9718                 if (!is_ok (&error))
9719                         goto leave;
9720                 mono_array_setref (typedargs, i, typedarg);
9721         }
9722
9723         for (i = 0; i < mono_array_length (namedargs); ++i) {
9724                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9725                 MonoObject *typedarg, *namedarg, *minfo;
9726
9727                 if (arginfo [i].prop) {
9728                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9729                         if (!minfo)
9730                                 goto leave;
9731                 } else {
9732                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9733                         if (!mono_error_ok (&error))
9734                                 goto leave;
9735                 }
9736
9737                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9738                 if (!is_ok (&error))
9739                         goto leave;
9740                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9741                 if (!is_ok (&error))
9742                         goto leave;
9743
9744                 mono_array_setref (namedargs, i, namedarg);
9745         }
9746
9747         *ctor_args = typedargs;
9748         *named_args = namedargs;
9749 leave:
9750         g_free (arginfo);
9751         mono_error_raise_exception (&error);
9752
9753 }
9754
9755 static MonoObject*
9756 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9757 {
9758         static MonoMethod *ctor;
9759
9760         MonoDomain *domain;
9761         MonoObject *attr;
9762         void *params [4];
9763
9764         mono_error_init (error);
9765
9766         g_assert (image->assembly);
9767
9768         if (!ctor)
9769                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9770
9771         domain = mono_domain_get ();
9772         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9773         return_val_if_nok (error, NULL);
9774         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9775         return_val_if_nok (error, NULL);
9776         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9777         return_val_if_nok (error, NULL);
9778         params [2] = (gpointer)&cattr->data;
9779         params [3] = &cattr->data_size;
9780
9781         mono_runtime_invoke_checked (ctor, attr, params, error);
9782         return_val_if_nok (error, NULL);
9783         return attr;
9784 }
9785
9786 static MonoArray*
9787 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9788 {
9789         MonoArray *result;
9790         MonoObject *attr;
9791         int i, n;
9792
9793         mono_error_init (error);
9794
9795         n = 0;
9796         for (i = 0; i < cinfo->num_attrs; ++i) {
9797                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9798                         n ++;
9799         }
9800
9801         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9802         n = 0;
9803         for (i = 0; i < cinfo->num_attrs; ++i) {
9804                 if (!cinfo->attrs [i].ctor) {
9805                         /* The cattr type is not finished yet */
9806                         /* We should include the type name but cinfo doesn't contain it */
9807                         mono_error_set_type_load_name (error, NULL, NULL, "");
9808                         return NULL;
9809                 }
9810                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9811                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9812                         if (!mono_error_ok (error))
9813                                 return result;
9814                         mono_array_setref (result, n, attr);
9815                         n ++;
9816                 }
9817         }
9818         return result;
9819 }
9820
9821 MonoArray*
9822 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9823 {
9824         MonoError error;
9825         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9826         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9827
9828         return result;
9829 }
9830
9831 static MonoArray*
9832 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9833 {
9834         MonoArray *result;
9835         MonoObject *attr;
9836         int i;
9837         
9838         mono_error_init (error);
9839         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9840         for (i = 0; i < cinfo->num_attrs; ++i) {
9841                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9842                 return_val_if_nok (error, NULL);
9843                 mono_array_setref (result, i, attr);
9844         }
9845         return result;
9846 }
9847
9848 /**
9849  * mono_custom_attrs_from_index:
9850  *
9851  * Returns: NULL if no attributes are found or if a loading error occurs.
9852  */
9853 MonoCustomAttrInfo*
9854 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9855 {
9856         MonoError error;
9857         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9858         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9859         return result;
9860 }
9861 /**
9862  * mono_custom_attrs_from_index_checked:
9863  *
9864  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9865  */
9866 MonoCustomAttrInfo*
9867 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9868 {
9869         guint32 mtoken, i, len;
9870         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9871         MonoTableInfo *ca;
9872         MonoCustomAttrInfo *ainfo;
9873         GList *tmp, *list = NULL;
9874         const char *data;
9875         MonoCustomAttrEntry* attr;
9876
9877         mono_error_init (error);
9878
9879         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9880
9881         i = mono_metadata_custom_attrs_from_index (image, idx);
9882         if (!i)
9883                 return NULL;
9884         i --;
9885         while (i < ca->rows) {
9886                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9887                         break;
9888                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9889                 ++i;
9890         }
9891         len = g_list_length (list);
9892         if (!len)
9893                 return NULL;
9894         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9895         ainfo->num_attrs = len;
9896         ainfo->image = image;
9897         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9898                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9899                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9900                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9901                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9902                         mtoken |= MONO_TOKEN_METHOD_DEF;
9903                         break;
9904                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9905                         mtoken |= MONO_TOKEN_MEMBER_REF;
9906                         break;
9907                 default:
9908                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9909                         break;
9910                 }
9911                 attr = &ainfo->attrs [i - 1];
9912                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9913                 if (!attr->ctor) {
9914                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9915                         g_list_free (list);
9916                         g_free (ainfo);
9917                         return NULL;
9918                 }
9919
9920                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9921                         /*FIXME raising an exception here doesn't make any sense*/
9922                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9923                         g_list_free (list);
9924                         g_free (ainfo);
9925                         return NULL;
9926                 }
9927                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9928                 attr->data_size = mono_metadata_decode_value (data, &data);
9929                 attr->data = (guchar*)data;
9930         }
9931         g_list_free (list);
9932
9933         return ainfo;
9934 }
9935
9936 MonoCustomAttrInfo*
9937 mono_custom_attrs_from_method (MonoMethod *method)
9938 {
9939         MonoError error;
9940         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9941         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9942         return result;
9943 }
9944
9945 MonoCustomAttrInfo*
9946 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9947 {
9948         guint32 idx;
9949
9950         mono_error_init (error);
9951
9952         /*
9953          * An instantiated method has the same cattrs as the generic method definition.
9954          *
9955          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9956          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9957          */
9958         if (method->is_inflated)
9959                 method = ((MonoMethodInflated *) method)->declaring;
9960         
9961         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9962                 return lookup_custom_attr (method->klass->image, method);
9963
9964         if (!method->token)
9965                 /* Synthetic methods */
9966                 return NULL;
9967
9968         idx = mono_method_get_index (method);
9969         idx <<= MONO_CUSTOM_ATTR_BITS;
9970         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9971         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9972 }
9973
9974 MonoCustomAttrInfo*
9975 mono_custom_attrs_from_class (MonoClass *klass)
9976 {
9977         MonoError error;
9978         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9979         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9980         return result;
9981 }
9982
9983 MonoCustomAttrInfo*
9984 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9985 {
9986         guint32 idx;
9987
9988         mono_error_init (error);
9989
9990         if (klass->generic_class)
9991                 klass = klass->generic_class->container_class;
9992
9993         if (image_is_dynamic (klass->image))
9994                 return lookup_custom_attr (klass->image, klass);
9995
9996         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9997                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9998                 idx <<= MONO_CUSTOM_ATTR_BITS;
9999                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10000         } else {
10001                 idx = mono_metadata_token_index (klass->type_token);
10002                 idx <<= MONO_CUSTOM_ATTR_BITS;
10003                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10004         }
10005         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10006 }
10007
10008 MonoCustomAttrInfo*
10009 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10010 {
10011         MonoError error;
10012         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10013         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10014         return result;
10015 }
10016
10017 MonoCustomAttrInfo*
10018 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10019 {
10020         guint32 idx;
10021         
10022         mono_error_init (error);
10023
10024         if (image_is_dynamic (assembly->image))
10025                 return lookup_custom_attr (assembly->image, assembly);
10026         idx = 1; /* there is only one assembly */
10027         idx <<= MONO_CUSTOM_ATTR_BITS;
10028         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10029         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10030 }
10031
10032 static MonoCustomAttrInfo*
10033 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10034 {
10035         guint32 idx;
10036         
10037         if (image_is_dynamic (image))
10038                 return lookup_custom_attr (image, image);
10039         idx = 1; /* there is only one module */
10040         idx <<= MONO_CUSTOM_ATTR_BITS;
10041         idx |= MONO_CUSTOM_ATTR_MODULE;
10042         return mono_custom_attrs_from_index_checked (image, idx, error);
10043 }
10044
10045 MonoCustomAttrInfo*
10046 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10047 {
10048         MonoError error;
10049         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10050         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10051         return result;
10052 }
10053
10054 MonoCustomAttrInfo*
10055 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10056 {
10057         guint32 idx;
10058         
10059         if (image_is_dynamic (klass->image)) {
10060                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10061                 return lookup_custom_attr (klass->image, property);
10062         }
10063         idx = find_property_index (klass, property);
10064         idx <<= MONO_CUSTOM_ATTR_BITS;
10065         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10066         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10067 }
10068
10069 MonoCustomAttrInfo*
10070 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10071 {
10072         MonoError error;
10073         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10074         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10075         return result;
10076 }
10077
10078 MonoCustomAttrInfo*
10079 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10080 {
10081         guint32 idx;
10082         
10083         if (image_is_dynamic (klass->image)) {
10084                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10085                 return lookup_custom_attr (klass->image, event);
10086         }
10087         idx = find_event_index (klass, event);
10088         idx <<= MONO_CUSTOM_ATTR_BITS;
10089         idx |= MONO_CUSTOM_ATTR_EVENT;
10090         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10091 }
10092
10093 MonoCustomAttrInfo*
10094 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10095 {
10096         MonoError error;
10097         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10098         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10099         return result;
10100 }
10101
10102 MonoCustomAttrInfo*
10103 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10104 {
10105         guint32 idx;
10106         mono_error_init (error);
10107
10108         if (image_is_dynamic (klass->image)) {
10109                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10110                 return lookup_custom_attr (klass->image, field);
10111         }
10112         idx = find_field_index (klass, field);
10113         idx <<= MONO_CUSTOM_ATTR_BITS;
10114         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10115         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10116 }
10117
10118 /**
10119  * mono_custom_attrs_from_param:
10120  * @method: handle to the method that we want to retrieve custom parameter information from
10121  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10122  *
10123  * The result must be released with mono_custom_attrs_free().
10124  *
10125  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10126  */
10127 MonoCustomAttrInfo*
10128 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10129 {
10130         MonoError error;
10131         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10132         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10133         return result;
10134 }
10135
10136 /**
10137  * mono_custom_attrs_from_param_checked:
10138  * @method: handle to the method that we want to retrieve custom parameter information from
10139  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10140  * @error: set on error
10141  *
10142  * The result must be released with mono_custom_attrs_free().
10143  *
10144  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10145  */
10146 MonoCustomAttrInfo*
10147 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10148 {
10149         MonoTableInfo *ca;
10150         guint32 i, idx, method_index;
10151         guint32 param_list, param_last, param_pos, found;
10152         MonoImage *image;
10153         MonoReflectionMethodAux *aux;
10154
10155         mono_error_init (error);
10156
10157         /*
10158          * An instantiated method has the same cattrs as the generic method definition.
10159          *
10160          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10161          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10162          */
10163         if (method->is_inflated)
10164                 method = ((MonoMethodInflated *) method)->declaring;
10165
10166         if (image_is_dynamic (method->klass->image)) {
10167                 MonoCustomAttrInfo *res, *ainfo;
10168                 int size;
10169
10170                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10171                 if (!aux || !aux->param_cattr)
10172                         return NULL;
10173
10174                 /* Need to copy since it will be freed later */
10175                 ainfo = aux->param_cattr [param];
10176                 if (!ainfo)
10177                         return NULL;
10178                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10179                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10180                 memcpy (res, ainfo, size);
10181                 return res;
10182         }
10183
10184         image = method->klass->image;
10185         method_index = mono_method_get_index (method);
10186         if (!method_index)
10187                 return NULL;
10188         ca = &image->tables [MONO_TABLE_METHOD];
10189
10190         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10191         if (method_index == ca->rows) {
10192                 ca = &image->tables [MONO_TABLE_PARAM];
10193                 param_last = ca->rows + 1;
10194         } else {
10195                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10196                 ca = &image->tables [MONO_TABLE_PARAM];
10197         }
10198         found = FALSE;
10199         for (i = param_list; i < param_last; ++i) {
10200                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10201                 if (param_pos == param) {
10202                         found = TRUE;
10203                         break;
10204                 }
10205         }
10206         if (!found)
10207                 return NULL;
10208         idx = i;
10209         idx <<= MONO_CUSTOM_ATTR_BITS;
10210         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10211         return mono_custom_attrs_from_index_checked (image, idx, error);
10212 }
10213
10214 gboolean
10215 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10216 {
10217         int i;
10218         MonoClass *klass;
10219         for (i = 0; i < ainfo->num_attrs; ++i) {
10220                 klass = ainfo->attrs [i].ctor->klass;
10221                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10222                         return TRUE;
10223         }
10224         return FALSE;
10225 }
10226
10227 MonoObject*
10228 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10229 {
10230         MonoError error;
10231         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10232         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10233         return res;
10234 }
10235
10236 MonoObject*
10237 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10238 {
10239         int i, attr_index;
10240         MonoClass *klass;
10241         MonoArray *attrs;
10242
10243         mono_error_init (error);
10244
10245         attr_index = -1;
10246         for (i = 0; i < ainfo->num_attrs; ++i) {
10247                 klass = ainfo->attrs [i].ctor->klass;
10248                 if (mono_class_has_parent (klass, attr_klass)) {
10249                         attr_index = i;
10250                         break;
10251                 }
10252         }
10253         if (attr_index == -1)
10254                 return NULL;
10255
10256         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10257         if (!mono_error_ok (error))
10258                 return NULL;
10259         return mono_array_get (attrs, MonoObject*, attr_index);
10260 }
10261
10262 /*
10263  * mono_reflection_get_custom_attrs_info:
10264  * @obj: a reflection object handle
10265  *
10266  * Return the custom attribute info for attributes defined for the
10267  * reflection handle @obj. The objects.
10268  *
10269  * FIXME this function leaks like a sieve for SRE objects.
10270  */
10271 MonoCustomAttrInfo*
10272 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10273 {
10274         MonoError error;
10275         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10276         mono_error_assert_ok (&error);
10277         return result;
10278 }
10279
10280 /**
10281  * mono_reflection_get_custom_attrs_info_checked:
10282  * @obj: a reflection object handle
10283  * @error: set on error
10284  *
10285  * Return the custom attribute info for attributes defined for the
10286  * reflection handle @obj. The objects.
10287  *
10288  * On failure returns NULL and sets @error.
10289  *
10290  * FIXME this function leaks like a sieve for SRE objects.
10291  */
10292 MonoCustomAttrInfo*
10293 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10294 {
10295         MonoClass *klass;
10296         MonoCustomAttrInfo *cinfo = NULL;
10297         
10298         mono_error_init (error);
10299
10300         klass = obj->vtable->klass;
10301         if (klass == mono_defaults.monotype_class) {
10302                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10303                 return_val_if_nok (error, NULL);
10304                 klass = mono_class_from_mono_type (type);
10305                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10306                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10307                 return_val_if_nok (error, NULL);
10308         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10309                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10310                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10311                 return_val_if_nok (error, NULL);
10312         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10313                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10314                 cinfo = mono_custom_attrs_from_module (module->image, error);
10315                 return_val_if_nok (error, NULL);
10316         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10317                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10318                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10319                 return_val_if_nok (error, NULL);
10320         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10321                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10322                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10323                 return_val_if_nok (error, NULL);
10324         } else if (strcmp ("MonoField", klass->name) == 0) {
10325                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10326                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10327                 return_val_if_nok (error, NULL);
10328         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10329                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10330                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10331                 return_val_if_nok (error, NULL);
10332         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10333                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10334                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10335                 return_val_if_nok (error, NULL);
10336         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10337                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10338                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10339                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10340                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10341                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10342                         return_val_if_nok (error, NULL);
10343                 } else if (is_sr_mono_property (member_class)) {
10344                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10345                         MonoMethod *method;
10346                         if (!(method = prop->property->get))
10347                                 method = prop->property->set;
10348                         g_assert (method);
10349
10350                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10351                         return_val_if_nok (error, NULL);
10352                 } 
10353 #ifndef DISABLE_REFLECTION_EMIT
10354                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10355                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10356                         return_val_if_nok (error, NULL);
10357                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10358                         return_val_if_nok (error, NULL);
10359                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10360                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10361                         MonoMethod *method = NULL;
10362                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10363                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10364                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10365                                 method = ((MonoReflectionMethod *)c->cb)->method;
10366                         else
10367                                 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));
10368
10369                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10370                         return_val_if_nok (error, NULL);
10371                 } 
10372 #endif
10373                 else {
10374                         char *type_name = mono_type_get_full_name (member_class);
10375                         mono_error_set_not_supported (error,
10376                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10377                                                       type_name);
10378                         g_free (type_name);
10379                         return NULL;
10380                 }
10381         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10382                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10383                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10384         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10385                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10386                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10387         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10388                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10389                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10390         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10391                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10392                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10393         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10394                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10395                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10396         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10397                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10398                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10399         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10400                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10401                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10402                 return_val_if_nok (error, NULL);
10403         } else { /* handle other types here... */
10404                 g_error ("get custom attrs not yet supported for %s", klass->name);
10405         }
10406
10407         return cinfo;
10408 }
10409
10410 /*
10411  * mono_reflection_get_custom_attrs_by_type:
10412  * @obj: a reflection object handle
10413  *
10414  * Return an array with all the custom attributes defined of the
10415  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10416  * of that type are returned. The objects are fully build. Return NULL if a loading error
10417  * occurs.
10418  */
10419 MonoArray*
10420 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10421 {
10422         MonoArray *result;
10423         MonoCustomAttrInfo *cinfo;
10424
10425         mono_error_init (error);
10426
10427         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10428         return_val_if_nok (error, NULL);
10429         if (cinfo) {
10430                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10431                 if (!result)
10432                         return NULL;
10433                 if (!cinfo->cached)
10434                         mono_custom_attrs_free (cinfo);
10435         } else {
10436                 mono_loader_assert_no_error ();
10437                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10438         }
10439
10440         return result;
10441 }
10442
10443 /*
10444  * mono_reflection_get_custom_attrs:
10445  * @obj: a reflection object handle
10446  *
10447  * Return an array with all the custom attributes defined of the
10448  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10449  * occurs.
10450  */
10451 MonoArray*
10452 mono_reflection_get_custom_attrs (MonoObject *obj)
10453 {
10454         MonoError error;
10455
10456         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10457 }
10458
10459 /*
10460  * mono_reflection_get_custom_attrs_data:
10461  * @obj: a reflection obj handle
10462  *
10463  * Returns an array of System.Reflection.CustomAttributeData,
10464  * which include information about attributes reflected on
10465  * types loaded using the Reflection Only methods
10466  */
10467 MonoArray*
10468 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10469 {
10470         MonoError error;
10471         MonoArray* result;
10472         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10473         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10474         return result;
10475 }
10476
10477 /*
10478  * mono_reflection_get_custom_attrs_data_checked:
10479  * @obj: a reflection obj handle
10480  * @error: set on error
10481  *
10482  * Returns an array of System.Reflection.CustomAttributeData,
10483  * which include information about attributes reflected on
10484  * types loaded using the Reflection Only methods
10485  */
10486 MonoArray*
10487 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10488 {
10489         MonoArray *result;
10490         MonoCustomAttrInfo *cinfo;
10491
10492         mono_error_init (error);
10493
10494         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10495         return_val_if_nok (error, NULL);
10496         if (cinfo) {
10497                 result = mono_custom_attrs_data_construct (cinfo, error);
10498                 return_val_if_nok (error, NULL);
10499                 if (!cinfo->cached)
10500                         mono_custom_attrs_free (cinfo);
10501         } else
10502                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10503
10504         if (mono_loader_get_last_error ())
10505                 mono_error_set_from_loader_error (error);
10506
10507         return result;
10508 }
10509
10510 static MonoReflectionType*
10511 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10512 {
10513         static MonoMethod *method_get_underlying_system_type = NULL;
10514         MonoReflectionType *rt;
10515         MonoMethod *usertype_method;
10516
10517         mono_error_init (error);
10518
10519         if (!method_get_underlying_system_type)
10520                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10521
10522         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10523
10524         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10525
10526         return rt;
10527 }
10528
10529
10530 static gboolean
10531 is_corlib_type (MonoClass *klass)
10532 {
10533         return klass->image == mono_defaults.corlib;
10534 }
10535
10536 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10537         static MonoClass *cached_class; \
10538         if (cached_class) \
10539                 return cached_class == _class; \
10540         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10541                 cached_class = _class; \
10542                 return TRUE; \
10543         } \
10544         return FALSE; \
10545 } while (0) \
10546
10547
10548 #ifndef DISABLE_REFLECTION_EMIT
10549 static gboolean
10550 is_sre_array (MonoClass *klass)
10551 {
10552         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10553 }
10554
10555 static gboolean
10556 is_sre_byref (MonoClass *klass)
10557 {
10558         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10559 }
10560
10561 static gboolean
10562 is_sre_pointer (MonoClass *klass)
10563 {
10564         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10565 }
10566
10567 static gboolean
10568 is_sre_generic_instance (MonoClass *klass)
10569 {
10570         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10571 }
10572
10573 static gboolean
10574 is_sre_type_builder (MonoClass *klass)
10575 {
10576         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10577 }
10578
10579 static gboolean
10580 is_sre_method_builder (MonoClass *klass)
10581 {
10582         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10583 }
10584
10585 static gboolean
10586 is_sre_ctor_builder (MonoClass *klass)
10587 {
10588         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10589 }
10590
10591 static gboolean
10592 is_sre_field_builder (MonoClass *klass)
10593 {
10594         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10595 }
10596
10597 static gboolean
10598 is_sre_method_on_tb_inst (MonoClass *klass)
10599 {
10600         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10601 }
10602
10603 static gboolean
10604 is_sre_ctor_on_tb_inst (MonoClass *klass)
10605 {
10606         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10607 }
10608
10609 MonoType*
10610 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10611 {
10612         MonoClass *klass;
10613         mono_error_init (error);
10614
10615         if (!ref)
10616                 return NULL;
10617         if (ref->type)
10618                 return ref->type;
10619
10620         if (is_usertype (ref)) {
10621                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10622                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10623                         return NULL;
10624                 if (ref->type)
10625                         return ref->type;
10626         }
10627
10628         klass = mono_object_class (ref);
10629
10630         if (is_sre_array (klass)) {
10631                 MonoType *res;
10632                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10633                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10634                 return_val_if_nok (error, NULL);
10635                 g_assert (base);
10636                 if (sre_array->rank == 0) //single dimentional array
10637                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10638                 else
10639                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10640                 sre_array->type.type = res;
10641                 return res;
10642         } else if (is_sre_byref (klass)) {
10643                 MonoType *res;
10644                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10645                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10646                 return_val_if_nok (error, NULL);
10647                 g_assert (base);
10648                 res = &mono_class_from_mono_type (base)->this_arg;
10649                 sre_byref->type.type = res;
10650                 return res;
10651         } else if (is_sre_pointer (klass)) {
10652                 MonoType *res;
10653                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10654                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10655                 return_val_if_nok (error, NULL);
10656                 g_assert (base);
10657                 res = &mono_ptr_class_get (base)->byval_arg;
10658                 sre_pointer->type.type = res;
10659                 return res;
10660         } else if (is_sre_generic_instance (klass)) {
10661                 MonoType *res, **types;
10662                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10663                 int i, count;
10664
10665                 count = mono_array_length (gclass->type_arguments);
10666                 types = g_new0 (MonoType*, count);
10667                 for (i = 0; i < count; ++i) {
10668                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10669                         types [i] = mono_reflection_type_get_handle (t, error);
10670                         if (!types[i] || !is_ok (error)) {
10671                                 g_free (types);
10672                                 return NULL;
10673                         }
10674                 }
10675
10676                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10677                 g_free (types);
10678                 g_assert (res);
10679                 gclass->type.type = res;
10680                 return res;
10681         }
10682
10683         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10684         return NULL;
10685 }
10686
10687 void
10688 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10689 {
10690         MonoError error;
10691         mono_reflection_type_get_handle (type, &error);
10692         mono_error_set_pending_exception (&error);
10693 }
10694
10695 static gboolean
10696 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10697 {
10698         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10699         MonoClass *klass;
10700
10701         mono_error_init (error);
10702
10703         MonoType *res = mono_reflection_type_get_handle (type, error);
10704
10705         if (!res && is_ok (error)) {
10706                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10707         }
10708         return_val_if_nok (error, FALSE);
10709
10710         klass = mono_class_from_mono_type (res);
10711
10712         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10713         mono_domain_lock (domain);
10714
10715         if (!image_is_dynamic (klass->image)) {
10716                 mono_class_setup_supertypes (klass);
10717         } else {
10718                 if (!domain->type_hash)
10719                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10720                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10721                 mono_g_hash_table_insert (domain->type_hash, res, type);
10722         }
10723         mono_domain_unlock (domain);
10724         mono_loader_unlock ();
10725
10726         return TRUE;
10727 }
10728
10729 void
10730 mono_reflection_register_with_runtime (MonoReflectionType *type)
10731 {
10732         MonoError error;
10733         (void) reflection_register_with_runtime (type, &error);
10734         mono_error_set_pending_exception (&error);
10735 }
10736
10737 /**
10738  * LOCKING: Assumes the loader lock is held.
10739  */
10740 static MonoMethodSignature*
10741 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10742         MonoMethodSignature *sig;
10743         int count, i;
10744
10745         mono_error_init (error);
10746
10747         count = parameters? mono_array_length (parameters): 0;
10748
10749         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10750         sig->param_count = count;
10751         sig->sentinelpos = -1; /* FIXME */
10752         for (i = 0; i < count; ++i) {
10753                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10754                 if (!is_ok (error)) {
10755                         image_g_free (image, sig);
10756                         return NULL;
10757                 }
10758         }
10759         return sig;
10760 }
10761
10762 /**
10763  * LOCKING: Assumes the loader lock is held.
10764  */
10765 static MonoMethodSignature*
10766 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10767         MonoMethodSignature *sig;
10768
10769         mono_error_init (error);
10770
10771         sig = parameters_to_signature (image, ctor->parameters, error);
10772         return_val_if_nok (error, NULL);
10773         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10774         sig->ret = &mono_defaults.void_class->byval_arg;
10775         return sig;
10776 }
10777
10778 /**
10779  * LOCKING: Assumes the loader lock is held.
10780  */
10781 static MonoMethodSignature*
10782 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10783         MonoMethodSignature *sig;
10784
10785         mono_error_init (error);
10786
10787         sig = parameters_to_signature (image, method->parameters, error);
10788         return_val_if_nok (error, NULL);
10789         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10790         if (method->rtype) {
10791                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10792                 if (!is_ok (error)) {
10793                         image_g_free (image, sig);
10794                         return NULL;
10795                 }
10796         } else {
10797                 sig->ret = &mono_defaults.void_class->byval_arg;
10798         }
10799         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10800         return sig;
10801 }
10802
10803 static MonoMethodSignature*
10804 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10805         MonoMethodSignature *sig;
10806
10807         mono_error_init (error);
10808
10809         sig = parameters_to_signature (NULL, method->parameters, error);
10810         return_val_if_nok (error, NULL);
10811         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10812         if (method->rtype) {
10813                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10814                 if (!is_ok (error)) {
10815                         g_free (sig);
10816                         return NULL;
10817                 }
10818         } else {
10819                 sig->ret = &mono_defaults.void_class->byval_arg;
10820         }
10821         sig->generic_param_count = 0;
10822         return sig;
10823 }
10824
10825 static void
10826 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10827 {
10828         mono_error_init (error);
10829         MonoClass *klass = mono_object_class (prop);
10830         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10831                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10832                 *name = mono_string_to_utf8 (pb->name);
10833                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10834         } else {
10835                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10836                 *name = g_strdup (p->property->name);
10837                 if (p->property->get)
10838                         *type = mono_method_signature (p->property->get)->ret;
10839                 else
10840                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10841         }
10842 }
10843
10844 static void
10845 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10846 {
10847         mono_error_init (error);
10848         MonoClass *klass = mono_object_class (field);
10849         if (strcmp (klass->name, "FieldBuilder") == 0) {
10850                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10851                 *name = mono_string_to_utf8 (fb->name);
10852                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10853         } else {
10854                 MonoReflectionField *f = (MonoReflectionField *)field;
10855                 *name = g_strdup (mono_field_get_name (f->field));
10856                 *type = f->field->type;
10857         }
10858 }
10859
10860 #else /* DISABLE_REFLECTION_EMIT */
10861
10862 void
10863 mono_reflection_register_with_runtime (MonoReflectionType *type)
10864 {
10865         /* This is empty */
10866 }
10867
10868 static gboolean
10869 is_sre_type_builder (MonoClass *klass)
10870 {
10871         return FALSE;
10872 }
10873
10874 static gboolean
10875 is_sre_generic_instance (MonoClass *klass)
10876 {
10877         return FALSE;
10878 }
10879
10880 static void
10881 init_type_builder_generics (MonoObject *type)
10882 {
10883 }
10884
10885 #endif /* !DISABLE_REFLECTION_EMIT */
10886
10887
10888 static gboolean
10889 is_sr_mono_field (MonoClass *klass)
10890 {
10891         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10892 }
10893
10894 static gboolean
10895 is_sr_mono_property (MonoClass *klass)
10896 {
10897         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10898 }
10899
10900 static gboolean
10901 is_sr_mono_method (MonoClass *klass)
10902 {
10903         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10904 }
10905
10906 static gboolean
10907 is_sr_mono_cmethod (MonoClass *klass)
10908 {
10909         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10910 }
10911
10912 static gboolean
10913 is_sr_mono_generic_method (MonoClass *klass)
10914 {
10915         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10916 }
10917
10918 static gboolean
10919 is_sr_mono_generic_cmethod (MonoClass *klass)
10920 {
10921         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10922 }
10923
10924 gboolean
10925 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10926 {
10927         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10928 }
10929
10930 static gboolean
10931 is_usertype (MonoReflectionType *ref)
10932 {
10933         MonoClass *klass = mono_object_class (ref);
10934         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10935 }
10936
10937 static MonoReflectionType*
10938 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10939 {
10940         mono_error_init (error);
10941         if (!type || type->type)
10942                 return type;
10943
10944         if (is_usertype (type)) {
10945                 type = mono_reflection_type_get_underlying_system_type (type, error);
10946                 return_val_if_nok (error, NULL);
10947                 if (is_usertype (type)) {
10948                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10949                         return NULL;
10950                 }
10951         }
10952
10953         return type;
10954 }
10955 /**
10956  * encode_cattr_value:
10957  * Encode a value in a custom attribute stream of bytes.
10958  * The value to encode is either supplied as an object in argument val
10959  * (valuetypes are boxed), or as a pointer to the data in the
10960  * argument argval.
10961  * @type represents the type of the value
10962  * @buffer is the start of the buffer
10963  * @p the current position in the buffer
10964  * @buflen contains the size of the buffer and is used to return the new buffer size
10965  * if this needs to be realloced.
10966  * @retbuffer and @retp return the start and the position of the buffer
10967  * @error set on error.
10968  */
10969 static void
10970 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10971 {
10972         MonoTypeEnum simple_type;
10973         
10974         mono_error_init (error);
10975         if ((p-buffer) + 10 >= *buflen) {
10976                 char *newbuf;
10977                 *buflen *= 2;
10978                 newbuf = (char *)g_realloc (buffer, *buflen);
10979                 p = newbuf + (p-buffer);
10980                 buffer = newbuf;
10981         }
10982         if (!argval)
10983                 argval = ((char*)arg + sizeof (MonoObject));
10984         simple_type = type->type;
10985 handle_enum:
10986         switch (simple_type) {
10987         case MONO_TYPE_BOOLEAN:
10988         case MONO_TYPE_U1:
10989         case MONO_TYPE_I1:
10990                 *p++ = *argval;
10991                 break;
10992         case MONO_TYPE_CHAR:
10993         case MONO_TYPE_U2:
10994         case MONO_TYPE_I2:
10995                 swap_with_size (p, argval, 2, 1);
10996                 p += 2;
10997                 break;
10998         case MONO_TYPE_U4:
10999         case MONO_TYPE_I4:
11000         case MONO_TYPE_R4:
11001                 swap_with_size (p, argval, 4, 1);
11002                 p += 4;
11003                 break;
11004         case MONO_TYPE_R8:
11005                 swap_with_size (p, argval, 8, 1);
11006                 p += 8;
11007                 break;
11008         case MONO_TYPE_U8:
11009         case MONO_TYPE_I8:
11010                 swap_with_size (p, argval, 8, 1);
11011                 p += 8;
11012                 break;
11013         case MONO_TYPE_VALUETYPE:
11014                 if (type->data.klass->enumtype) {
11015                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11016                         goto handle_enum;
11017                 } else {
11018                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11019                 }
11020                 break;
11021         case MONO_TYPE_STRING: {
11022                 char *str;
11023                 guint32 slen;
11024                 if (!arg) {
11025                         *p++ = 0xFF;
11026                         break;
11027                 }
11028                 str = mono_string_to_utf8 ((MonoString*)arg);
11029                 slen = strlen (str);
11030                 if ((p-buffer) + 10 + slen >= *buflen) {
11031                         char *newbuf;
11032                         *buflen *= 2;
11033                         *buflen += slen;
11034                         newbuf = (char *)g_realloc (buffer, *buflen);
11035                         p = newbuf + (p-buffer);
11036                         buffer = newbuf;
11037                 }
11038                 mono_metadata_encode_value (slen, p, &p);
11039                 memcpy (p, str, slen);
11040                 p += slen;
11041                 g_free (str);
11042                 break;
11043         }
11044         case MONO_TYPE_CLASS: {
11045                 char *str;
11046                 guint32 slen;
11047                 MonoType *arg_type;
11048                 if (!arg) {
11049                         *p++ = 0xFF;
11050                         break;
11051                 }
11052 handle_type:
11053                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11054                 return_if_nok (error);
11055
11056                 str = type_get_qualified_name (arg_type, NULL);
11057                 slen = strlen (str);
11058                 if ((p-buffer) + 10 + slen >= *buflen) {
11059                         char *newbuf;
11060                         *buflen *= 2;
11061                         *buflen += slen;
11062                         newbuf = (char *)g_realloc (buffer, *buflen);
11063                         p = newbuf + (p-buffer);
11064                         buffer = newbuf;
11065                 }
11066                 mono_metadata_encode_value (slen, p, &p);
11067                 memcpy (p, str, slen);
11068                 p += slen;
11069                 g_free (str);
11070                 break;
11071         }
11072         case MONO_TYPE_SZARRAY: {
11073                 int len, i;
11074                 MonoClass *eclass, *arg_eclass;
11075
11076                 if (!arg) {
11077                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11078                         break;
11079                 }
11080                 len = mono_array_length ((MonoArray*)arg);
11081                 *p++ = len & 0xff;
11082                 *p++ = (len >> 8) & 0xff;
11083                 *p++ = (len >> 16) & 0xff;
11084                 *p++ = (len >> 24) & 0xff;
11085                 *retp = p;
11086                 *retbuffer = buffer;
11087                 eclass = type->data.klass;
11088                 arg_eclass = mono_object_class (arg)->element_class;
11089
11090                 if (!eclass) {
11091                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11092                         eclass = mono_defaults.object_class;
11093                 }
11094                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11095                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11096                         int elsize = mono_class_array_element_size (arg_eclass);
11097                         for (i = 0; i < len; ++i) {
11098                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11099                                 return_if_nok (error);
11100                                 elptr += elsize;
11101                         }
11102                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11103                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11104                         int elsize = mono_class_array_element_size (eclass);
11105                         for (i = 0; i < len; ++i) {
11106                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11107                                 return_if_nok (error);
11108                                 elptr += elsize;
11109                         }
11110                 } else {
11111                         for (i = 0; i < len; ++i) {
11112                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11113                                 return_if_nok (error);
11114                         }
11115                 }
11116                 break;
11117         }
11118         case MONO_TYPE_OBJECT: {
11119                 MonoClass *klass;
11120                 char *str;
11121                 guint32 slen;
11122
11123                 /*
11124                  * The parameter type is 'object' but the type of the actual
11125                  * argument is not. So we have to add type information to the blob
11126                  * too. This is completely undocumented in the spec.
11127                  */
11128
11129                 if (arg == NULL) {
11130                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11131                         *p++ = 0xFF;
11132                         break;
11133                 }
11134                 
11135                 klass = mono_object_class (arg);
11136
11137                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11138                         *p++ = 0x50;
11139                         goto handle_type;
11140                 } else {
11141                         return_if_nok (error);
11142                 }
11143
11144                 if (klass->enumtype) {
11145                         *p++ = 0x55;
11146                 } else if (klass == mono_defaults.string_class) {
11147                         simple_type = MONO_TYPE_STRING;
11148                         *p++ = 0x0E;
11149                         goto handle_enum;
11150                 } else if (klass->rank == 1) {
11151                         *p++ = 0x1D;
11152                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11153                                 /* See Partition II, Appendix B3 */
11154                                 *p++ = 0x51;
11155                         else
11156                                 *p++ = klass->element_class->byval_arg.type;
11157                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11158                         return_if_nok (error);
11159                         break;
11160                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11161                         *p++ = simple_type = klass->byval_arg.type;
11162                         goto handle_enum;
11163                 } else {
11164                         g_error ("unhandled type in custom attr");
11165                 }
11166                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11167                 slen = strlen (str);
11168                 if ((p-buffer) + 10 + slen >= *buflen) {
11169                         char *newbuf;
11170                         *buflen *= 2;
11171                         *buflen += slen;
11172                         newbuf = (char *)g_realloc (buffer, *buflen);
11173                         p = newbuf + (p-buffer);
11174                         buffer = newbuf;
11175                 }
11176                 mono_metadata_encode_value (slen, p, &p);
11177                 memcpy (p, str, slen);
11178                 p += slen;
11179                 g_free (str);
11180                 simple_type = mono_class_enum_basetype (klass)->type;
11181                 goto handle_enum;
11182         }
11183         default:
11184                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11185         }
11186         *retp = p;
11187         *retbuffer = buffer;
11188 }
11189
11190 static void
11191 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11192 {
11193         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11194                 char *str = type_get_qualified_name (type, NULL);
11195                 int slen = strlen (str);
11196
11197                 *p++ = 0x55;
11198                 /*
11199                  * This seems to be optional...
11200                  * *p++ = 0x80;
11201                  */
11202                 mono_metadata_encode_value (slen, p, &p);
11203                 memcpy (p, str, slen);
11204                 p += slen;
11205                 g_free (str);
11206         } else if (type->type == MONO_TYPE_OBJECT) {
11207                 *p++ = 0x51;
11208         } else if (type->type == MONO_TYPE_CLASS) {
11209                 /* it should be a type: encode_cattr_value () has the check */
11210                 *p++ = 0x50;
11211         } else {
11212                 mono_metadata_encode_value (type->type, p, &p);
11213                 if (type->type == MONO_TYPE_SZARRAY)
11214                         /* See the examples in Partition VI, Annex B */
11215                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11216         }
11217
11218         *retp = p;
11219 }
11220
11221 #ifndef DISABLE_REFLECTION_EMIT
11222 static void
11223 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11224 {
11225         int len;
11226
11227         mono_error_init (error);
11228
11229         /* Preallocate a large enough buffer */
11230         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11231                 char *str = type_get_qualified_name (type, NULL);
11232                 len = strlen (str);
11233                 g_free (str);
11234         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11235                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11236                 len = strlen (str);
11237                 g_free (str);
11238         } else {
11239                 len = 0;
11240         }
11241         len += strlen (name);
11242
11243         if ((p-buffer) + 20 + len >= *buflen) {
11244                 char *newbuf;
11245                 *buflen *= 2;
11246                 *buflen += len;
11247                 newbuf = (char *)g_realloc (buffer, *buflen);
11248                 p = newbuf + (p-buffer);
11249                 buffer = newbuf;
11250         }
11251
11252         encode_field_or_prop_type (type, p, &p);
11253
11254         len = strlen (name);
11255         mono_metadata_encode_value (len, p, &p);
11256         memcpy (p, name, len);
11257         p += len;
11258         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11259         return_if_nok (error);
11260         *retp = p;
11261         *retbuffer = buffer;
11262 }
11263
11264 /**
11265  * mono_reflection_get_custom_attrs_blob:
11266  * @ctor: custom attribute constructor
11267  * @ctorArgs: arguments o the constructor
11268  * @properties:
11269  * @propValues:
11270  * @fields:
11271  * @fieldValues:
11272  * 
11273  * Creates the blob of data that needs to be saved in the metadata and that represents
11274  * the custom attributed described by @ctor, @ctorArgs etc.
11275  * Returns: a Byte array representing the blob of data.
11276  */
11277 MonoArray*
11278 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11279 {
11280         MonoError error;
11281         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11282         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11283         return result;
11284 }
11285
11286 /**
11287  * mono_reflection_get_custom_attrs_blob_checked:
11288  * @ctor: custom attribute constructor
11289  * @ctorArgs: arguments o the constructor
11290  * @properties:
11291  * @propValues:
11292  * @fields:
11293  * @fieldValues:
11294  * @error: set on error
11295  * 
11296  * Creates the blob of data that needs to be saved in the metadata and that represents
11297  * the custom attributed described by @ctor, @ctorArgs etc.
11298  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11299  */
11300 MonoArray*
11301 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11302 {
11303         MonoArray *result = NULL;
11304         MonoMethodSignature *sig;
11305         MonoObject *arg;
11306         char *buffer, *p;
11307         guint32 buflen, i;
11308
11309         mono_error_init (error);
11310
11311         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11312                 /* sig is freed later so allocate it in the heap */
11313                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11314                 if (!is_ok (error)) {
11315                         g_free (sig);
11316                         return NULL;
11317                 }
11318         } else {
11319                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11320         }
11321
11322         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11323         buflen = 256;
11324         p = buffer = (char *)g_malloc (buflen);
11325         /* write the prolog */
11326         *p++ = 1;
11327         *p++ = 0;
11328         for (i = 0; i < sig->param_count; ++i) {
11329                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11330                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11331                 if (!is_ok (error)) goto leave;
11332         }
11333         i = 0;
11334         if (properties)
11335                 i += mono_array_length (properties);
11336         if (fields)
11337                 i += mono_array_length (fields);
11338         *p++ = i & 0xff;
11339         *p++ = (i >> 8) & 0xff;
11340         if (properties) {
11341                 MonoObject *prop;
11342                 for (i = 0; i < mono_array_length (properties); ++i) {
11343                         MonoType *ptype;
11344                         char *pname;
11345
11346                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11347                         get_prop_name_and_type (prop, &pname, &ptype, error);
11348                         if (!is_ok (error)) goto leave;
11349                         *p++ = 0x54; /* PROPERTY signature */
11350                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11351                         g_free (pname);
11352                         if (!is_ok (error)) goto leave;
11353                 }
11354         }
11355
11356         if (fields) {
11357                 MonoObject *field;
11358                 for (i = 0; i < mono_array_length (fields); ++i) {
11359                         MonoType *ftype;
11360                         char *fname;
11361
11362                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11363                         get_field_name_and_type (field, &fname, &ftype, error);
11364                         if (!is_ok (error)) goto leave;
11365                         *p++ = 0x53; /* FIELD signature */
11366                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11367                         g_free (fname);
11368                         if (!is_ok (error)) goto leave;
11369                 }
11370         }
11371
11372         g_assert (p - buffer <= buflen);
11373         buflen = p - buffer;
11374         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11375         p = mono_array_addr (result, char, 0);
11376         memcpy (p, buffer, buflen);
11377 leave:
11378         g_free (buffer);
11379         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11380                 g_free (sig);
11381         return result;
11382 }
11383
11384 /**
11385  * reflection_setup_internal_class:
11386  * @tb: a TypeBuilder object
11387  * @error: set on error
11388  *
11389  * Creates a MonoClass that represents the TypeBuilder.
11390  * This is a trick that lets us simplify a lot of reflection code
11391  * (and will allow us to support Build and Run assemblies easier).
11392  *
11393  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11394  */
11395 static gboolean
11396 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11397 {
11398         MonoClass *klass, *parent;
11399
11400         mono_error_init (error);
11401         RESOLVE_TYPE (tb->parent, error);
11402         return_val_if_nok (error, FALSE);
11403
11404         mono_loader_lock ();
11405
11406         if (tb->parent) {
11407                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11408                 if (!is_ok (error)) {
11409                         mono_loader_unlock ();
11410                         return FALSE;
11411                 }
11412                 /* check so we can compile corlib correctly */
11413                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11414                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11415                         parent = parent_type->data.klass;
11416                 } else {
11417                         parent = mono_class_from_mono_type (parent_type);
11418                 }
11419         } else {
11420                 parent = NULL;
11421         }
11422         
11423         /* the type has already being created: it means we just have to change the parent */
11424         if (tb->type.type) {
11425                 klass = mono_class_from_mono_type (tb->type.type);
11426                 klass->parent = NULL;
11427                 /* fool mono_class_setup_parent */
11428                 klass->supertypes = NULL;
11429                 mono_class_setup_parent (klass, parent);
11430                 mono_class_setup_mono_type (klass);
11431                 mono_loader_unlock ();
11432                 return TRUE;
11433         }
11434
11435         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11436
11437         klass->image = &tb->module->dynamic_image->image;
11438
11439         klass->inited = 1; /* we lie to the runtime */
11440         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11441         if (!is_ok (error))
11442                 goto failure;
11443         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11444         if (!is_ok (error))
11445                 goto failure;
11446         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11447         klass->flags = tb->attrs;
11448         
11449         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11450
11451         klass->element_class = klass;
11452
11453         if (mono_class_get_ref_info (klass) == NULL) {
11454
11455                 mono_class_set_ref_info (klass, tb);
11456
11457                 /* Put into cache so mono_class_get_checked () will find it.
11458                 Skip nested types as those should not be available on the global scope. */
11459                 if (!tb->nesting_type)
11460                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11461
11462                 /*
11463                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11464                 by performing a mono_class_get which does the full resolution.
11465
11466                 Working around this semantics would require us to write a lot of code for no clear advantage.
11467                 */
11468                 mono_image_append_class_to_reflection_info_set (klass);
11469         } else {
11470                 g_assert (mono_class_get_ref_info (klass) == tb);
11471         }
11472
11473         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11474
11475         if (parent != NULL) {
11476                 mono_class_setup_parent (klass, parent);
11477         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11478                 const char *old_n = klass->name;
11479                 /* trick to get relative numbering right when compiling corlib */
11480                 klass->name = "BuildingObject";
11481                 mono_class_setup_parent (klass, mono_defaults.object_class);
11482                 klass->name = old_n;
11483         }
11484
11485         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11486                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11487                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11488                 klass->instance_size = sizeof (MonoObject);
11489                 klass->size_inited = 1;
11490                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11491         }
11492
11493         mono_class_setup_mono_type (klass);
11494
11495         mono_class_setup_supertypes (klass);
11496
11497         /*
11498          * FIXME: handle interfaces.
11499          */
11500
11501         tb->type.type = &klass->byval_arg;
11502
11503         if (tb->nesting_type) {
11504                 g_assert (tb->nesting_type->type);
11505                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11506                 if (!is_ok (error)) goto failure;
11507                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11508         }
11509
11510         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11511
11512         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11513         
11514         mono_loader_unlock ();
11515         return TRUE;
11516
11517 failure:
11518         mono_loader_unlock ();
11519         return FALSE;
11520 }
11521
11522 /**
11523  * mono_reflection_setup_internal_class:
11524  * @tb: a TypeBuilder object
11525  *
11526  * (icall)
11527  * Creates a MonoClass that represents the TypeBuilder.
11528  * This is a trick that lets us simplify a lot of reflection code
11529  * (and will allow us to support Build and Run assemblies easier).
11530  *
11531  */
11532 void
11533 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11534 {
11535         MonoError error;
11536         (void) reflection_setup_internal_class (tb, &error);
11537         mono_error_set_pending_exception (&error);
11538 }
11539
11540 /*
11541  * mono_reflection_setup_generic_class:
11542  * @tb: a TypeBuilder object
11543  *
11544  * Setup the generic class before adding the first generic parameter.
11545  */
11546 void
11547 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11548 {
11549 }
11550
11551 /*
11552  * mono_reflection_create_generic_class:
11553  * @tb: a TypeBuilder object
11554  *
11555  * Creates the generic class after all generic parameters have been added.
11556  */
11557 void
11558 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11559 {
11560         MonoError error;
11561         MonoClass *klass;
11562         int count, i;
11563
11564         klass = mono_class_from_mono_type (tb->type.type);
11565
11566         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11567
11568         if (klass->generic_container || (count == 0))
11569                 return;
11570
11571         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11572
11573         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11574
11575         klass->generic_container->owner.klass = klass;
11576         klass->generic_container->type_argc = count;
11577         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11578
11579         klass->is_generic = 1;
11580
11581         for (i = 0; i < count; i++) {
11582                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11583                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11584                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11585                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11586                 klass->generic_container->type_params [i] = *param;
11587                 /*Make sure we are a diferent type instance */
11588                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11589                 klass->generic_container->type_params [i].info.pklass = NULL;
11590                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11591
11592                 g_assert (klass->generic_container->type_params [i].param.owner);
11593         }
11594
11595         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11596 }
11597
11598 /**
11599  * reflection_create_internal_class:
11600  * @tb: a TypeBuilder object
11601  * @error: set on error
11602  *
11603  * Actually create the MonoClass that is associated with the TypeBuilder.
11604  * On success returns TRUE, on failure returns FALSE and sets @error.
11605  *
11606  */
11607 static gboolean
11608 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11609 {
11610
11611         MonoClass *klass;
11612
11613         mono_error_init (error);
11614         klass = mono_class_from_mono_type (tb->type.type);
11615
11616         mono_loader_lock ();
11617         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11618                 MonoReflectionFieldBuilder *fb;
11619                 MonoClass *ec;
11620                 MonoType *enum_basetype;
11621
11622                 g_assert (tb->fields != NULL);
11623                 g_assert (mono_array_length (tb->fields) >= 1);
11624
11625                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11626
11627                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11628                 if (!is_ok (error)) {
11629                         mono_loader_unlock ();
11630                         return FALSE;
11631                 }
11632                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11633                         mono_loader_unlock ();
11634                         return TRUE;
11635                 }
11636
11637                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11638                 if (!is_ok (error)) {
11639                         mono_loader_unlock ();
11640                         return FALSE;
11641                 }
11642                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11643                 if (!klass->element_class)
11644                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11645
11646                 /*
11647                  * get the element_class from the current corlib.
11648                  */
11649                 ec = default_class_from_mono_type (enum_basetype);
11650                 klass->instance_size = ec->instance_size;
11651                 klass->size_inited = 1;
11652                 /* 
11653                  * this is almost safe to do with enums and it's needed to be able
11654                  * to create objects of the enum type (for use in SetConstant).
11655                  */
11656                 /* FIXME: Does this mean enums can't have method overrides ? */
11657                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11658         }
11659         mono_loader_unlock ();
11660         return TRUE;
11661 }
11662
11663 /**
11664  * mono_reflection_create_internal_class:
11665  * @tb: a TypeBuilder object
11666  *
11667  * (icall)
11668  * Actually create the MonoClass that is associated with the TypeBuilder.
11669  */
11670 void
11671 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11672 {
11673         MonoError error;
11674         (void) reflection_create_internal_class (tb, &error);
11675         mono_error_set_pending_exception (&error);
11676 }
11677
11678 static MonoMarshalSpec*
11679 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11680                                 MonoReflectionMarshal *minfo, MonoError *error)
11681 {
11682         MonoMarshalSpec *res;
11683
11684         mono_error_init (error);
11685
11686         res = image_g_new0 (image, MonoMarshalSpec, 1);
11687         res->native = (MonoMarshalNative)minfo->type;
11688
11689         switch (minfo->type) {
11690         case MONO_NATIVE_LPARRAY:
11691                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11692                 if (minfo->has_size) {
11693                         res->data.array_data.param_num = minfo->param_num;
11694                         res->data.array_data.num_elem = minfo->count;
11695                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11696                 }
11697                 else {
11698                         res->data.array_data.param_num = -1;
11699                         res->data.array_data.num_elem = -1;
11700                         res->data.array_data.elem_mult = -1;
11701                 }
11702                 break;
11703
11704         case MONO_NATIVE_BYVALTSTR:
11705         case MONO_NATIVE_BYVALARRAY:
11706                 res->data.array_data.num_elem = minfo->count;
11707                 break;
11708
11709         case MONO_NATIVE_CUSTOM:
11710                 if (minfo->marshaltyperef) {
11711                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11712                         if (!is_ok (error)) {
11713                                 image_g_free (image, res);
11714                                 return NULL;
11715                         }
11716                         res->data.custom_data.custom_name =
11717                                 type_get_fully_qualified_name (marshaltyperef);
11718                 }
11719                 if (minfo->mcookie)
11720                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11721                 break;
11722
11723         default:
11724                 break;
11725         }
11726
11727         return res;
11728 }
11729 #endif /* !DISABLE_REFLECTION_EMIT */
11730
11731 MonoReflectionMarshalAsAttribute*
11732 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11733                                                         MonoMarshalSpec *spec, MonoError *error)
11734 {
11735         MonoReflectionType *rt;
11736         MonoReflectionMarshalAsAttribute *minfo;
11737         MonoType *mtype;
11738
11739         mono_error_init (error);
11740         
11741         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11742         if (!minfo)
11743                 return NULL;
11744         minfo->utype = spec->native;
11745
11746         switch (minfo->utype) {
11747         case MONO_NATIVE_LPARRAY:
11748                 minfo->array_subtype = spec->data.array_data.elem_type;
11749                 minfo->size_const = spec->data.array_data.num_elem;
11750                 if (spec->data.array_data.param_num != -1)
11751                         minfo->size_param_index = spec->data.array_data.param_num;
11752                 break;
11753
11754         case MONO_NATIVE_BYVALTSTR:
11755         case MONO_NATIVE_BYVALARRAY:
11756                 minfo->size_const = spec->data.array_data.num_elem;
11757                 break;
11758
11759         case MONO_NATIVE_CUSTOM:
11760                 if (spec->data.custom_data.custom_name) {
11761                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11762                         return_val_if_nok  (error, NULL);
11763
11764                         if (mtype) {
11765                                 rt = mono_type_get_object_checked (domain, mtype, error);
11766                                 if (!rt)
11767                                         return NULL;
11768
11769                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11770                         }
11771
11772                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11773                 }
11774                 if (spec->data.custom_data.cookie)
11775                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11776                 break;
11777
11778         default:
11779                 break;
11780         }
11781
11782         return minfo;
11783 }
11784
11785 #ifndef DISABLE_REFLECTION_EMIT
11786 static MonoMethod*
11787 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11788                                          ReflectionMethodBuilder *rmb,
11789                                          MonoMethodSignature *sig)
11790 {
11791         MonoError error;
11792         MonoMethod *m;
11793         MonoMethodWrapper *wrapperm;
11794         MonoMarshalSpec **specs;
11795         MonoReflectionMethodAux *method_aux;
11796         MonoImage *image;
11797         gboolean dynamic;
11798         int i;
11799
11800         mono_error_init (&error);
11801         /*
11802          * Methods created using a MethodBuilder should have their memory allocated
11803          * inside the image mempool, while dynamic methods should have their memory
11804          * malloc'd.
11805          */
11806         dynamic = rmb->refs != NULL;
11807         image = dynamic ? NULL : klass->image;
11808
11809         if (!dynamic)
11810                 g_assert (!klass->generic_class);
11811
11812         mono_loader_lock ();
11813
11814         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11815                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11816                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11817         else
11818                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11819
11820         wrapperm = (MonoMethodWrapper*)m;
11821
11822         m->dynamic = dynamic;
11823         m->slot = -1;
11824         m->flags = rmb->attrs;
11825         m->iflags = rmb->iattrs;
11826         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11827         m->klass = klass;
11828         m->signature = sig;
11829         m->sre_method = TRUE;
11830         m->skip_visibility = rmb->skip_visibility;
11831         if (rmb->table_idx)
11832                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11833
11834         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11835                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11836                         m->string_ctor = 1;
11837
11838                 m->signature->pinvoke = 1;
11839         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11840                 m->signature->pinvoke = 1;
11841
11842                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11843
11844                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11845                 g_assert (mono_error_ok (&error));
11846                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11847                 g_assert (mono_error_ok (&error));
11848                 
11849                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11850
11851                 if (image_is_dynamic (klass->image))
11852                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11853
11854                 mono_loader_unlock ();
11855
11856                 return m;
11857         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11858                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11859                 MonoMethodHeader *header;
11860                 guint32 code_size;
11861                 gint32 max_stack, i;
11862                 gint32 num_locals = 0;
11863                 gint32 num_clauses = 0;
11864                 guint8 *code;
11865
11866                 if (rmb->ilgen) {
11867                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11868                         code_size = rmb->ilgen->code_len;
11869                         max_stack = rmb->ilgen->max_stack;
11870                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11871                         if (rmb->ilgen->ex_handlers)
11872                                 num_clauses = method_count_clauses (rmb->ilgen);
11873                 } else {
11874                         if (rmb->code) {
11875                                 code = mono_array_addr (rmb->code, guint8, 0);
11876                                 code_size = mono_array_length (rmb->code);
11877                                 /* we probably need to run a verifier on the code... */
11878                                 max_stack = 8; 
11879                         }
11880                         else {
11881                                 code = NULL;
11882                                 code_size = 0;
11883                                 max_stack = 8;
11884                         }
11885                 }
11886
11887                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11888                 header->code_size = code_size;
11889                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11890                 memcpy ((char*)header->code, code, code_size);
11891                 header->max_stack = max_stack;
11892                 header->init_locals = rmb->init_locals;
11893                 header->num_locals = num_locals;
11894
11895                 for (i = 0; i < num_locals; ++i) {
11896                         MonoReflectionLocalBuilder *lb = 
11897                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11898
11899                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11900                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11901                         mono_error_assert_ok (&error);
11902                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11903                 }
11904
11905                 header->num_clauses = num_clauses;
11906                 if (num_clauses) {
11907                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11908                                                                  rmb->ilgen, num_clauses, &error);
11909                         mono_error_assert_ok (&error);
11910                 }
11911
11912                 wrapperm->header = header;
11913         }
11914
11915         if (rmb->generic_params) {
11916                 int count = mono_array_length (rmb->generic_params);
11917                 MonoGenericContainer *container = rmb->generic_container;
11918
11919                 g_assert (container);
11920
11921                 container->type_argc = count;
11922                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11923                 container->owner.method = m;
11924                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11925
11926                 m->is_generic = TRUE;
11927                 mono_method_set_generic_container (m, container);
11928
11929                 for (i = 0; i < count; i++) {
11930                         MonoReflectionGenericParam *gp =
11931                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11932                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11933                         mono_error_assert_ok (&error);
11934                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11935                         container->type_params [i] = *param;
11936                 }
11937
11938                 /*
11939                  * The method signature might have pointers to generic parameters that belong to other methods.
11940                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11941                  * generic parameters.
11942                  */
11943                 for (i = 0; i < m->signature->param_count; ++i) {
11944                         MonoType *t = m->signature->params [i];
11945                         if (t->type == MONO_TYPE_MVAR) {
11946                                 MonoGenericParam *gparam =  t->data.generic_param;
11947                                 if (gparam->num < count) {
11948                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11949                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11950                                 }
11951
11952                         }
11953                 }
11954
11955                 if (klass->generic_container) {
11956                         container->parent = klass->generic_container;
11957                         container->context.class_inst = klass->generic_container->context.class_inst;
11958                 }
11959                 container->context.method_inst = mono_get_shared_generic_inst (container);
11960         }
11961
11962         if (rmb->refs) {
11963                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11964                 int i;
11965                 void **data;
11966
11967                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11968
11969                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11970                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11971                 for (i = 0; i < rmb->nrefs; ++i)
11972                         data [i + 1] = rmb->refs [i];
11973         }
11974
11975         method_aux = NULL;
11976
11977         /* Parameter info */
11978         if (rmb->pinfo) {
11979                 if (!method_aux)
11980                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11981                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11982                 for (i = 0; i <= m->signature->param_count; ++i) {
11983                         MonoReflectionParamBuilder *pb;
11984                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11985                                 if ((i > 0) && (pb->attrs)) {
11986                                         /* Make a copy since it might point to a shared type structure */
11987                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11988                                         m->signature->params [i - 1]->attrs = pb->attrs;
11989                                 }
11990
11991                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11992                                         MonoDynamicImage *assembly;
11993                                         guint32 idx, len;
11994                                         MonoTypeEnum def_type;
11995                                         char *p;
11996                                         const char *p2;
11997
11998                                         if (!method_aux->param_defaults) {
11999                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12000                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12001                                         }
12002                                         assembly = (MonoDynamicImage*)klass->image;
12003                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12004                                         /* Copy the data from the blob since it might get realloc-ed */
12005                                         p = assembly->blob.data + idx;
12006                                         len = mono_metadata_decode_blob_size (p, &p2);
12007                                         len += p2 - p;
12008                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12009                                         method_aux->param_default_types [i] = def_type;
12010                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12011                                 }
12012
12013                                 if (pb->name) {
12014                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12015                                         g_assert (mono_error_ok (&error));
12016                                 }
12017                                 if (pb->cattrs) {
12018                                         if (!method_aux->param_cattr)
12019                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12020                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12021                                 }
12022                         }
12023                 }
12024         }
12025
12026         /* Parameter marshalling */
12027         specs = NULL;
12028         if (rmb->pinfo)         
12029                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12030                         MonoReflectionParamBuilder *pb;
12031                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12032                                 if (pb->marshal_info) {
12033                                         if (specs == NULL)
12034                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12035                                         specs [pb->position] = 
12036                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12037                                         if (!is_ok (&error)) {
12038                                                 mono_loader_unlock ();
12039                                                 image_g_free (image, specs);
12040                                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12041                                         }
12042                                 }
12043                         }
12044                 }
12045         if (specs != NULL) {
12046                 if (!method_aux)
12047                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12048                 method_aux->param_marshall = specs;
12049         }
12050
12051         if (image_is_dynamic (klass->image) && method_aux)
12052                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12053
12054         mono_loader_unlock ();
12055
12056         return m;
12057 }       
12058
12059 static MonoMethod*
12060 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12061 {
12062         ReflectionMethodBuilder rmb;
12063         MonoMethodSignature *sig;
12064
12065         mono_loader_lock ();
12066         g_assert (klass->image != NULL);
12067         sig = ctor_builder_to_signature (klass->image, mb, error);
12068         mono_loader_unlock ();
12069         return_val_if_nok (error, NULL);
12070
12071         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12072                 return NULL;
12073
12074         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12075         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12076
12077         /* If we are in a generic class, we might be called multiple times from inflate_method */
12078         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12079                 /* ilgen is no longer needed */
12080                 mb->ilgen = NULL;
12081         }
12082
12083         return mb->mhandle;
12084 }
12085
12086 static MonoMethod*
12087 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12088 {
12089         ReflectionMethodBuilder rmb;
12090         MonoMethodSignature *sig;
12091
12092         mono_error_init (error);
12093
12094         mono_loader_lock ();
12095         g_assert (klass->image != NULL);
12096         sig = method_builder_to_signature (klass->image, mb, error);
12097         mono_loader_unlock ();
12098         return_val_if_nok (error, NULL);
12099
12100         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12101                 return NULL;
12102
12103         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12104         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12105
12106         /* If we are in a generic class, we might be called multiple times from inflate_method */
12107         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12108                 /* ilgen is no longer needed */
12109                 mb->ilgen = NULL;
12110         }
12111         return mb->mhandle;
12112 }
12113
12114 static MonoClassField*
12115 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12116 {
12117         MonoClassField *field;
12118         MonoType *custom;
12119
12120         mono_error_init (error);
12121
12122         field = g_new0 (MonoClassField, 1);
12123
12124         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12125         mono_error_assert_ok (error);
12126         if (fb->attrs || fb->modreq || fb->modopt) {
12127                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12128                 if (!is_ok (error)) {
12129                         g_free (field);
12130                         return NULL;
12131                 }
12132                 field->type = mono_metadata_type_dup (NULL, type);
12133                 field->type->attrs = fb->attrs;
12134
12135                 g_assert (image_is_dynamic (klass->image));
12136                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12137                 g_free (field->type);
12138                 if (!is_ok (error)) {
12139                         g_free (field);
12140                         return NULL;
12141                 }
12142                 field->type = mono_metadata_type_dup (klass->image, custom);
12143                 g_free (custom);
12144         } else {
12145                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12146                 if (!is_ok (error)) {
12147                         g_free (field);
12148                         return NULL;
12149                 }
12150         }
12151         if (fb->offset != -1)
12152                 field->offset = fb->offset;
12153         field->parent = klass;
12154         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12155
12156         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12157
12158         return field;
12159 }
12160 #endif
12161
12162 /**
12163  * mono_reflection_bind_generic_parameters:
12164  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12165  * @type_args: the number of type arguments to bind
12166  * @types: array of type arguments
12167  * @error: set on error
12168  *
12169  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12170  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12171  */
12172 MonoType*
12173 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12174 {
12175         MonoClass *klass;
12176         MonoReflectionTypeBuilder *tb = NULL;
12177         gboolean is_dynamic = FALSE;
12178         MonoClass *geninst;
12179
12180         mono_error_init (error);
12181         
12182         mono_loader_lock ();
12183
12184         if (is_sre_type_builder (mono_object_class (type))) {
12185                 tb = (MonoReflectionTypeBuilder *) type;
12186
12187                 is_dynamic = TRUE;
12188         } else if (is_sre_generic_instance (mono_object_class (type))) {
12189                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12190                 MonoReflectionType *gtd = rgi->generic_type;
12191
12192                 if (is_sre_type_builder (mono_object_class (gtd))) {
12193                         tb = (MonoReflectionTypeBuilder *)gtd;
12194                         is_dynamic = TRUE;
12195                 }
12196         }
12197
12198         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12199         if (tb && tb->generic_container)
12200                 mono_reflection_create_generic_class (tb);
12201
12202         MonoType *t = mono_reflection_type_get_handle (type, error);
12203         if (!is_ok (error)) {
12204                 mono_loader_unlock ();
12205                 return NULL;
12206         }
12207
12208         klass = mono_class_from_mono_type (t);
12209         if (!klass->generic_container) {
12210                 mono_loader_unlock ();
12211                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12212                 return NULL;
12213         }
12214
12215         if (klass->wastypebuilder) {
12216                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12217
12218                 is_dynamic = TRUE;
12219         }
12220
12221         mono_loader_unlock ();
12222
12223         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12224
12225         return &geninst->byval_arg;
12226 }
12227
12228 MonoClass*
12229 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12230 {
12231         MonoGenericClass *gclass;
12232         MonoGenericInst *inst;
12233
12234         g_assert (klass->generic_container);
12235
12236         inst = mono_metadata_get_generic_inst (type_argc, types);
12237         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12238
12239         return mono_generic_class_get_class (gclass);
12240 }
12241
12242 MonoReflectionMethod*
12243 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12244 {
12245         MonoError error;
12246         MonoClass *klass;
12247         MonoMethod *method, *inflated;
12248         MonoMethodInflated *imethod;
12249         MonoGenericContext tmp_context;
12250         MonoGenericInst *ginst;
12251         MonoType **type_argv;
12252         int count, i;
12253
12254         /*FIXME but this no longer should happen*/
12255         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12256 #ifndef DISABLE_REFLECTION_EMIT
12257                 MonoReflectionMethodBuilder *mb = NULL;
12258                 MonoType *tb;
12259                 MonoClass *klass;
12260
12261                 mb = (MonoReflectionMethodBuilder *) rmethod;
12262                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12263                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12264                 klass = mono_class_from_mono_type (tb);
12265
12266                 method = methodbuilder_to_mono_method (klass, mb, &error);
12267                 if (!method)
12268                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12269 #else
12270                 g_assert_not_reached ();
12271                 method = NULL;
12272 #endif
12273         } else {
12274                 method = rmethod->method;
12275         }
12276
12277         klass = method->klass;
12278
12279         if (method->is_inflated)
12280                 method = ((MonoMethodInflated *) method)->declaring;
12281
12282         count = mono_method_signature (method)->generic_param_count;
12283         if (count != mono_array_length (types))
12284                 return NULL;
12285
12286         type_argv = g_new0 (MonoType *, count);
12287         for (i = 0; i < count; i++) {
12288                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12289                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12290                 if (!is_ok (&error)) {
12291                         g_free (type_argv);
12292                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12293                 }
12294         }
12295         ginst = mono_metadata_get_generic_inst (count, type_argv);
12296         g_free (type_argv);
12297
12298         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12299         tmp_context.method_inst = ginst;
12300
12301         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12302         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12303         imethod = (MonoMethodInflated *) inflated;
12304
12305         /*FIXME but I think this is no longer necessary*/
12306         if (image_is_dynamic (method->klass->image)) {
12307                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12308                 /*
12309                  * This table maps metadata structures representing inflated methods/fields
12310                  * to the reflection objects representing their generic definitions.
12311                  */
12312                 mono_image_lock ((MonoImage*)image);
12313                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12314                 mono_image_unlock ((MonoImage*)image);
12315         }
12316
12317         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12318                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12319         
12320         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12321         mono_error_raise_exception (&error); /* FIXME don't raise here */
12322         return ret;
12323 }
12324
12325 #ifndef DISABLE_REFLECTION_EMIT
12326
12327 static MonoMethod *
12328 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12329 {
12330         MonoMethodInflated *imethod;
12331         MonoGenericContext *context;
12332         int i;
12333
12334         /*
12335          * With generic code sharing the klass might not be inflated.
12336          * This can happen because classes inflated with their own
12337          * type arguments are "normalized" to the uninflated class.
12338          */
12339         if (!klass->generic_class)
12340                 return method;
12341
12342         context = mono_class_get_context (klass);
12343
12344         if (klass->method.count && klass->methods) {
12345                 /* Find the already created inflated method */
12346                 for (i = 0; i < klass->method.count; ++i) {
12347                         g_assert (klass->methods [i]->is_inflated);
12348                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12349                                 break;
12350                 }
12351                 g_assert (i < klass->method.count);
12352                 imethod = (MonoMethodInflated*)klass->methods [i];
12353         } else {
12354                 MonoError error;
12355                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12356                 mono_error_assert_ok (&error);
12357         }
12358
12359         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12360                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12361
12362                 mono_image_lock ((MonoImage*)image);
12363                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12364                 mono_image_unlock ((MonoImage*)image);
12365         }
12366         return (MonoMethod *) imethod;
12367 }
12368
12369 static MonoMethod *
12370 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12371 {
12372         MonoMethod *method;
12373         MonoClass *gklass;
12374
12375         mono_error_init (error);
12376
12377         MonoClass *type_class = mono_object_class (type);
12378
12379         if (is_sre_generic_instance (type_class)) {
12380                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12381                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12382                 return_val_if_nok (error, NULL);
12383                 gklass = mono_class_from_mono_type (generic_type);
12384         } else if (is_sre_type_builder (type_class)) {
12385                 MonoType *t = mono_reflection_type_get_handle (type, error);
12386                 return_val_if_nok (error, NULL);
12387                 gklass = mono_class_from_mono_type (t);
12388         } else if (type->type) {
12389                 gklass = mono_class_from_mono_type (type->type);
12390                 gklass = mono_class_get_generic_type_definition (gklass);
12391         } else {
12392                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12393         }
12394
12395         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12396                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12397                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12398                 else {
12399                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12400                         if (!method)
12401                                 return NULL;
12402                 }
12403         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12404                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12405                 if (!method)
12406                         return NULL;
12407         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12408                 method = ((MonoReflectionMethod *) obj)->method;
12409         else {
12410                 method = NULL; /* prevent compiler warning */
12411                 g_error ("can't handle type %s", obj->vtable->klass->name);
12412         }
12413
12414         MonoType *t = mono_reflection_type_get_handle (type, error);
12415         return_val_if_nok (error, NULL);
12416         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12417 }
12418
12419 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12420 static gboolean
12421 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12422 {
12423         MonoGenericClass *gclass;
12424         MonoDynamicGenericClass *dgclass;
12425         MonoClass *klass, *gklass;
12426         MonoType *gtype;
12427         int i;
12428
12429         mono_error_init (error);
12430
12431         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12432         return_val_if_nok (error, FALSE);
12433         klass = mono_class_from_mono_type (gtype);
12434         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12435         gclass = gtype->data.generic_class;
12436
12437         if (!gclass->is_dynamic)
12438                 return TRUE;
12439
12440         dgclass = (MonoDynamicGenericClass *) gclass;
12441
12442         if (dgclass->initialized)
12443                 return TRUE;
12444
12445         gklass = gclass->container_class;
12446         mono_class_init (gklass);
12447
12448         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12449
12450         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12451         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12452         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12453
12454         for (i = 0; i < dgclass->count_fields; i++) {
12455                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12456                 MonoClassField *field, *inflated_field = NULL;
12457
12458                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12459                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12460                         return_val_if_nok (error, FALSE);
12461                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12462                         field = ((MonoReflectionField *) obj)->field;
12463                 else {
12464                         field = NULL; /* prevent compiler warning */
12465                         g_assert_not_reached ();
12466                 }
12467
12468                 dgclass->fields [i] = *field;
12469                 dgclass->fields [i].parent = klass;
12470                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12471                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12472                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12473                 dgclass->field_generic_types [i] = field->type;
12474                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12475                 dgclass->field_objects [i] = obj;
12476
12477                 if (inflated_field) {
12478                         g_free (inflated_field);
12479                 } else {
12480                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12481                 }
12482         }
12483
12484         dgclass->initialized = TRUE;
12485         return TRUE;
12486 }
12487
12488 void
12489 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12490 {
12491         MonoError error;
12492         (void) reflection_generic_class_initialize (type, fields, &error);
12493         mono_error_set_pending_exception (&error);
12494 }
12495
12496 void
12497 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12498 {
12499         MonoDynamicGenericClass *dgclass;
12500         int i;
12501
12502         g_assert (gclass->is_dynamic);
12503
12504         dgclass = (MonoDynamicGenericClass *)gclass;
12505
12506         for (i = 0; i < dgclass->count_fields; ++i) {
12507                 MonoClassField *field = dgclass->fields + i;
12508                 mono_metadata_free_type (field->type);
12509                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12510         }
12511 }
12512
12513 /**
12514  * fix_partial_generic_class:
12515  * @klass: a generic instantiation MonoClass
12516  * @error: set on error
12517  *
12518  * Assumes that the generic container of @klass has its vtable
12519  * initialized, and updates the parent class, insterfaces, methods and
12520  * fields of @klass by inflating the types using the generic context.
12521  *
12522  * On success returns TRUE, on failure returns FALSE and sets @error.
12523  *
12524  */
12525 static gboolean
12526 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12527 {
12528         MonoClass *gklass = klass->generic_class->container_class;
12529         MonoDynamicGenericClass *dgclass;
12530         int i;
12531
12532         mono_error_init (error);
12533
12534         if (klass->wastypebuilder)
12535                 return TRUE;
12536
12537         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12538         if (klass->parent != gklass->parent) {
12539                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12540                 if (mono_error_ok (error)) {
12541                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12542                         mono_metadata_free_type (parent_type);
12543                         if (parent != klass->parent) {
12544                                 /*fool mono_class_setup_parent*/
12545                                 klass->supertypes = NULL;
12546                                 mono_class_setup_parent (klass, parent);
12547                         }
12548                 } else {
12549                         if (gklass->wastypebuilder)
12550                                 klass->wastypebuilder = TRUE;
12551                         return FALSE;
12552                 }
12553         }
12554
12555         if (!dgclass->initialized)
12556                 return TRUE;
12557
12558         if (klass->method.count != gklass->method.count) {
12559                 klass->method.count = gklass->method.count;
12560                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12561
12562                 for (i = 0; i < klass->method.count; i++) {
12563                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12564                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12565                         mono_error_assert_ok (error);
12566                 }
12567         }
12568
12569         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12570                 klass->interface_count = gklass->interface_count;
12571                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12572                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12573
12574                 for (i = 0; i < gklass->interface_count; ++i) {
12575                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12576                         return_val_if_nok (error, FALSE);
12577
12578                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12579                         mono_metadata_free_type (iface_type);
12580
12581                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12582                                 return FALSE;
12583                 }
12584                 klass->interfaces_inited = 1;
12585         }
12586
12587         if (klass->field.count != gklass->field.count) {
12588                 klass->field.count = gklass->field.count;
12589                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12590
12591                 for (i = 0; i < klass->field.count; i++) {
12592                         klass->fields [i] = gklass->fields [i];
12593                         klass->fields [i].parent = klass;
12594                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12595                         return_val_if_nok (error, FALSE);
12596                 }
12597         }
12598
12599         /*We can only finish with this klass once it's parent has as well*/
12600         if (gklass->wastypebuilder)
12601                 klass->wastypebuilder = TRUE;
12602         return TRUE;
12603 }
12604
12605 /**
12606  * ensure_generic_class_runtime_vtable:
12607  * @klass a generic class
12608  * @error set on error
12609  *
12610  * Ensures that the generic container of @klass has a vtable and
12611  * returns TRUE on success.  On error returns FALSE and sets @error.
12612  */
12613 static gboolean
12614 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12615 {
12616         MonoClass *gklass = klass->generic_class->container_class;
12617
12618         mono_error_init (error);
12619
12620         if (!ensure_runtime_vtable (gklass, error))
12621                 return FALSE;
12622
12623         return fix_partial_generic_class (klass, error);
12624 }
12625
12626 /**
12627  * ensure_runtime_vtable:
12628  * @klass the class
12629  * @error set on error
12630  *
12631  * Ensures that @klass has a vtable and returns TRUE on success. On
12632  * error returns FALSE and sets @error.
12633  */
12634 static gboolean
12635 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12636 {
12637         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12638         int i, num, j;
12639
12640         mono_error_init (error);
12641
12642         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12643                 return TRUE;
12644         if (klass->parent)
12645                 if (!ensure_runtime_vtable (klass->parent, error))
12646                         return FALSE;
12647
12648         if (tb) {
12649                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12650                 num += tb->num_methods;
12651                 klass->method.count = num;
12652                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12653                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12654                 for (i = 0; i < num; ++i) {
12655                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12656                         if (!ctor)
12657                                 return FALSE;
12658                         klass->methods [i] = ctor;
12659                 }
12660                 num = tb->num_methods;
12661                 j = i;
12662                 for (i = 0; i < num; ++i) {
12663                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12664                         if (!meth)
12665                                 return FALSE;
12666                         klass->methods [j++] = meth;
12667                 }
12668         
12669                 if (tb->interfaces) {
12670                         klass->interface_count = mono_array_length (tb->interfaces);
12671                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12672                         for (i = 0; i < klass->interface_count; ++i) {
12673                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12674                                 return_val_if_nok (error, FALSE);
12675                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12676                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12677                                         return FALSE;
12678                         }
12679                         klass->interfaces_inited = 1;
12680                 }
12681         } else if (klass->generic_class){
12682                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12683                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12684                         return FALSE;
12685                 }
12686         }
12687
12688         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12689                 int slot_num = 0;
12690                 for (i = 0; i < klass->method.count; ++i) {
12691                         MonoMethod *im = klass->methods [i];
12692                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12693                                 im->slot = slot_num++;
12694                 }
12695                 
12696                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12697                 mono_class_setup_interface_offsets (klass);
12698                 mono_class_setup_interface_id (klass);
12699         }
12700
12701         /*
12702          * The generic vtable is needed even if image->run is not set since some
12703          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12704          * method->slot being defined.
12705          */
12706
12707         /* 
12708          * tb->methods could not be freed since it is used for determining 
12709          * overrides during dynamic vtable construction.
12710          */
12711
12712         return TRUE;
12713 }
12714
12715 static MonoMethod*
12716 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12717 {
12718         mono_error_init (error);
12719         MonoClass *klass = mono_object_class (method);
12720         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12721                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12722                 return sr_method->method;
12723         }
12724         if (is_sre_method_builder (klass)) {
12725                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12726                 return mb->mhandle;
12727         }
12728         if (is_sre_method_on_tb_inst (klass)) {
12729                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12730                 MonoMethod *result;
12731                 /*FIXME move this to a proper method and unify with resolve_object*/
12732                 if (m->method_args) {
12733                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12734                 } else {
12735                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12736                         return_val_if_nok (error, NULL);
12737                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12738                         MonoMethod *mono_method;
12739
12740                         if (is_sre_method_builder (mono_object_class (m->mb)))
12741                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12742                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12743                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12744                         else
12745                                 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)));
12746
12747                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12748                 }
12749                 return result;
12750         }
12751
12752         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12753         return NULL;
12754 }
12755
12756 void
12757 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12758 {
12759         MonoReflectionTypeBuilder *tb;
12760         int i, j, onum;
12761         MonoReflectionMethod *m;
12762
12763         mono_error_init (error);
12764         *overrides = NULL;
12765         *num_overrides = 0;
12766
12767         g_assert (image_is_dynamic (klass->image));
12768
12769         if (!mono_class_get_ref_info (klass))
12770                 return;
12771
12772         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12773
12774         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12775
12776         onum = 0;
12777         if (tb->methods) {
12778                 for (i = 0; i < tb->num_methods; ++i) {
12779                         MonoReflectionMethodBuilder *mb = 
12780                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12781                         if (mb->override_methods)
12782                                 onum += mono_array_length (mb->override_methods);
12783                 }
12784         }
12785
12786         if (onum) {
12787                 *overrides = g_new0 (MonoMethod*, onum * 2);
12788
12789                 onum = 0;
12790                 for (i = 0; i < tb->num_methods; ++i) {
12791                         MonoReflectionMethodBuilder *mb = 
12792                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12793                         if (mb->override_methods) {
12794                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12795                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12796
12797                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12798                                         return_if_nok (error);
12799                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12800
12801                                         g_assert (mb->mhandle);
12802
12803                                         onum ++;
12804                                 }
12805                         }
12806                 }
12807         }
12808
12809         *num_overrides = onum;
12810 }
12811
12812 static void
12813 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12814 {
12815         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12816         MonoReflectionFieldBuilder *fb;
12817         MonoClassField *field;
12818         MonoImage *image = klass->image;
12819         const char *p, *p2;
12820         int i;
12821         guint32 len, idx, real_size = 0;
12822
12823         klass->field.count = tb->num_fields;
12824         klass->field.first = 0;
12825
12826         mono_error_init (error);
12827
12828         if (tb->class_size) {
12829                 if ((tb->packing_size & 0xffffff00) != 0) {
12830                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12831                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12832                         return;
12833                 }
12834                 klass->packing_size = tb->packing_size;
12835                 real_size = klass->instance_size + tb->class_size;
12836         }
12837
12838         if (!klass->field.count) {
12839                 klass->instance_size = MAX (klass->instance_size, real_size);
12840                 return;
12841         }
12842         
12843         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12844         mono_class_alloc_ext (klass);
12845         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12846         /*
12847         This is, guess what, a hack.
12848         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12849         On the static path no field class is resolved, only types are built. This is the right thing to do
12850         but we suck.
12851         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12852         */
12853         klass->size_inited = 1;
12854
12855         for (i = 0; i < klass->field.count; ++i) {
12856                 MonoArray *rva_data;
12857                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12858                 field = &klass->fields [i];
12859                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12860                 if (!mono_error_ok (error))
12861                         return;
12862                 if (fb->attrs) {
12863                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12864                         return_if_nok (error);
12865                         field->type = mono_metadata_type_dup (klass->image, type);
12866                         field->type->attrs = fb->attrs;
12867                 } else {
12868                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12869                         return_if_nok (error);
12870                 }
12871
12872                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12873                         char *base = mono_array_addr (rva_data, char, 0);
12874                         size_t size = mono_array_length (rva_data);
12875                         char *data = (char *)mono_image_alloc (klass->image, size);
12876                         memcpy (data, base, size);
12877                         klass->ext->field_def_values [i].data = data;
12878                 }
12879                 if (fb->offset != -1)
12880                         field->offset = fb->offset;
12881                 field->parent = klass;
12882                 fb->handle = field;
12883                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12884
12885                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12886                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12887                 }
12888                 if (fb->def_value) {
12889                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12890                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12891                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12892                         /* Copy the data from the blob since it might get realloc-ed */
12893                         p = assembly->blob.data + idx;
12894                         len = mono_metadata_decode_blob_size (p, &p2);
12895                         len += p2 - p;
12896                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12897                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12898                 }
12899         }
12900
12901         klass->instance_size = MAX (klass->instance_size, real_size);
12902         mono_class_layout_fields (klass, klass->instance_size);
12903 }
12904
12905 static void
12906 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12907 {
12908         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12909         MonoReflectionPropertyBuilder *pb;
12910         MonoImage *image = klass->image;
12911         MonoProperty *properties;
12912         int i;
12913
12914         mono_error_init (error);
12915
12916         if (!klass->ext)
12917                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12918
12919         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12920         klass->ext->property.first = 0;
12921
12922         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12923         klass->ext->properties = properties;
12924         for (i = 0; i < klass->ext->property.count; ++i) {
12925                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12926                 properties [i].parent = klass;
12927                 properties [i].attrs = pb->attrs;
12928                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12929                 if (!mono_error_ok (error))
12930                         return;
12931                 if (pb->get_method)
12932                         properties [i].get = pb->get_method->mhandle;
12933                 if (pb->set_method)
12934                         properties [i].set = pb->set_method->mhandle;
12935
12936                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12937                 if (pb->def_value) {
12938                         guint32 len, idx;
12939                         const char *p, *p2;
12940                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12941                         if (!klass->ext->prop_def_values)
12942                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12943                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12944                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12945                         /* Copy the data from the blob since it might get realloc-ed */
12946                         p = assembly->blob.data + idx;
12947                         len = mono_metadata_decode_blob_size (p, &p2);
12948                         len += p2 - p;
12949                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12950                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12951                 }
12952         }
12953 }
12954
12955 static MonoReflectionEvent *
12956 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12957 {
12958         mono_error_init (error);
12959
12960         MonoEvent *event = g_new0 (MonoEvent, 1);
12961         MonoClass *klass;
12962
12963         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12964         if (!is_ok (error)) {
12965                 g_free (event);
12966                 return NULL;
12967         }
12968         klass = mono_class_from_mono_type (type);
12969
12970         event->parent = klass;
12971         event->attrs = eb->attrs;
12972         event->name = mono_string_to_utf8 (eb->name);
12973         if (eb->add_method)
12974                 event->add = eb->add_method->mhandle;
12975         if (eb->remove_method)
12976                 event->remove = eb->remove_method->mhandle;
12977         if (eb->raise_method)
12978                 event->raise = eb->raise_method->mhandle;
12979
12980 #ifndef MONO_SMALL_CONFIG
12981         if (eb->other_methods) {
12982                 int j;
12983                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12984                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12985                         MonoReflectionMethodBuilder *mb = 
12986                                 mono_array_get (eb->other_methods,
12987                                                 MonoReflectionMethodBuilder*, j);
12988                         event->other [j] = mb->mhandle;
12989                 }
12990         }
12991 #endif
12992
12993         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12994         if (!is_ok (error)) {
12995 #ifndef MONO_SMALL_CONFIG
12996                 g_free (event->other);
12997 #endif
12998                 g_free (event);
12999                 return NULL;
13000         }
13001         return ev_obj;
13002 }
13003
13004 MonoReflectionEvent *
13005 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13006 {
13007         MonoError error;
13008         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13009         mono_error_set_pending_exception (&error);
13010         return result;
13011 }
13012
13013 static void
13014 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13015 {
13016         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13017         MonoReflectionEventBuilder *eb;
13018         MonoImage *image = klass->image;
13019         MonoEvent *events;
13020         int i;
13021
13022         mono_error_init (error);
13023
13024         if (!klass->ext)
13025                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13026
13027         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13028         klass->ext->event.first = 0;
13029
13030         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13031         klass->ext->events = events;
13032         for (i = 0; i < klass->ext->event.count; ++i) {
13033                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13034                 events [i].parent = klass;
13035                 events [i].attrs = eb->attrs;
13036                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13037                 if (!mono_error_ok (error))
13038                         return;
13039                 if (eb->add_method)
13040                         events [i].add = eb->add_method->mhandle;
13041                 if (eb->remove_method)
13042                         events [i].remove = eb->remove_method->mhandle;
13043                 if (eb->raise_method)
13044                         events [i].raise = eb->raise_method->mhandle;
13045
13046 #ifndef MONO_SMALL_CONFIG
13047                 if (eb->other_methods) {
13048                         int j;
13049                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13050                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13051                                 MonoReflectionMethodBuilder *mb = 
13052                                         mono_array_get (eb->other_methods,
13053                                                                         MonoReflectionMethodBuilder*, j);
13054                                 events [i].other [j] = mb->mhandle;
13055                         }
13056                 }
13057 #endif
13058                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13059         }
13060 }
13061
13062 struct remove_instantiations_user_data
13063 {
13064         MonoClass *klass;
13065         MonoError *error;
13066 };
13067
13068 static gboolean
13069 remove_instantiations_of_and_ensure_contents (gpointer key,
13070                                                   gpointer value,
13071                                                   gpointer user_data)
13072 {
13073         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13074         MonoType *type = (MonoType*)key;
13075         MonoClass *klass = data->klass;
13076         gboolean already_failed = !is_ok (data->error);
13077         MonoError lerror;
13078         MonoError *error = already_failed ? &lerror : data->error;
13079
13080         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13081                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13082                 //Ensure it's safe to use it.
13083                 if (!fix_partial_generic_class (inst_klass, error)) {
13084                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13085                         // Marked the class with failure, but since some other instantiation already failed,
13086                         // just report that one, and swallow the error from this one.
13087                         if (already_failed)
13088                                 mono_error_cleanup (error);
13089                 }
13090                 return TRUE;
13091         } else
13092                 return FALSE;
13093 }
13094
13095 static void
13096 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13097 {
13098         mono_error_init (error);
13099         int i;
13100
13101         if (!arr)
13102                 return;
13103
13104         for (i = 0; i < mono_array_length (arr); ++i) {
13105                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13106                 if (!mono_error_ok (error))
13107                         break;
13108         }
13109 }
13110
13111 MonoReflectionType*
13112 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13113 {
13114         MonoError error;
13115         MonoClass *klass;
13116         MonoDomain* domain;
13117         MonoReflectionType* res;
13118         int i, j;
13119
13120         mono_error_init (&error);
13121
13122         domain = mono_object_domain (tb);
13123         klass = mono_class_from_mono_type (tb->type.type);
13124
13125         /*
13126          * Check for user defined Type subclasses.
13127          */
13128         RESOLVE_TYPE (tb->parent, &error);
13129         if (!is_ok (&error))
13130                 goto failure_unlocked;
13131         check_array_for_usertypes (tb->interfaces, &error);
13132         if (!is_ok (&error))
13133                 goto failure_unlocked;
13134         if (tb->fields) {
13135                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13136                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13137                         if (fb) {
13138                                 RESOLVE_TYPE (fb->type, &error);
13139                                 if (!is_ok (&error))
13140                                         goto failure_unlocked;
13141                                 check_array_for_usertypes (fb->modreq, &error);
13142                                 if (!is_ok (&error))
13143                                         goto failure_unlocked;
13144                                 check_array_for_usertypes (fb->modopt, &error);
13145                                 if (!is_ok (&error))
13146                                         goto failure_unlocked;
13147                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13148                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13149                                         if (!is_ok (&error))
13150                                                 goto failure_unlocked;
13151                                 }
13152                         }
13153                 }
13154         }
13155         if (tb->methods) {
13156                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13157                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13158                         if (mb) {
13159                                 RESOLVE_TYPE (mb->rtype, &error);
13160                                 if (!is_ok (&error))
13161                                         goto failure_unlocked;
13162                                 check_array_for_usertypes (mb->return_modreq, &error);
13163                                 if (!is_ok (&error))
13164                                         goto failure_unlocked;
13165                                 check_array_for_usertypes (mb->return_modopt, &error);
13166                                 if (!is_ok (&error))
13167                                         goto failure_unlocked;
13168                                 check_array_for_usertypes (mb->parameters, &error);
13169                                 if (!is_ok (&error))
13170                                         goto failure_unlocked;
13171                                 if (mb->param_modreq)
13172                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13173                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13174                                                 if (!is_ok (&error))
13175                                                         goto failure_unlocked;
13176                                         }
13177                                 if (mb->param_modopt)
13178                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13179                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13180                                                 if (!is_ok (&error))
13181                                                         goto failure_unlocked;
13182                                         }
13183                         }
13184                 }
13185         }
13186         if (tb->ctors) {
13187                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13188                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13189                         if (mb) {
13190                                 check_array_for_usertypes (mb->parameters, &error);
13191                                 if (!is_ok (&error))
13192                                         goto failure_unlocked;
13193                                 if (mb->param_modreq)
13194                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13195                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13196                                                 if (!is_ok (&error))
13197                                                         goto failure_unlocked;
13198                                         }
13199                                 if (mb->param_modopt)
13200                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13201                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13202                                                 if (!is_ok (&error))
13203                                                         goto failure_unlocked;
13204                                         }
13205                         }
13206                 }
13207         }
13208
13209         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13210
13211         /* 
13212          * we need to lock the domain because the lock will be taken inside
13213          * So, we need to keep the locking order correct.
13214          */
13215         mono_loader_lock ();
13216         mono_domain_lock (domain);
13217         if (klass->wastypebuilder) {
13218                 mono_domain_unlock (domain);
13219                 mono_loader_unlock ();
13220
13221                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13222                 mono_error_set_pending_exception (&error);
13223
13224                 return res;
13225         }
13226         /*
13227          * Fields to set in klass:
13228          * the various flags: delegate/unicode/contextbound etc.
13229          */
13230         klass->flags = tb->attrs;
13231         klass->has_cctor = 1;
13232         klass->has_finalize = 1;
13233         klass->has_finalize_inited = 1;
13234
13235         mono_class_setup_parent (klass, klass->parent);
13236         /* fool mono_class_setup_supertypes */
13237         klass->supertypes = NULL;
13238         mono_class_setup_supertypes (klass);
13239         mono_class_setup_mono_type (klass);
13240
13241 #if 0
13242         if (!((MonoDynamicImage*)klass->image)->run) {
13243                 if (klass->generic_container) {
13244                         /* FIXME: The code below can't handle generic classes */
13245                         klass->wastypebuilder = TRUE;
13246                         mono_loader_unlock ();
13247                         mono_domain_unlock (domain);
13248
13249                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13250                         mono_error_set_pending_exception (&error);
13251
13252                         return res;
13253                 }
13254         }
13255 #endif
13256
13257         /* enums are done right away */
13258         if (!klass->enumtype)
13259                 if (!ensure_runtime_vtable (klass, &error))
13260                         goto failure;
13261
13262         if (tb->subtypes) {
13263                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13264                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13265                         mono_class_alloc_ext (klass);
13266                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13267                         if (!is_ok (&error)) goto failure;
13268                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13269                 }
13270         }
13271
13272         klass->nested_classes_inited = TRUE;
13273
13274         /* fields and object layout */
13275         if (klass->parent) {
13276                 if (!klass->parent->size_inited)
13277                         mono_class_init (klass->parent);
13278                 klass->instance_size = klass->parent->instance_size;
13279                 klass->sizes.class_size = 0;
13280                 klass->min_align = klass->parent->min_align;
13281                 /* if the type has no fields we won't call the field_setup
13282                  * routine which sets up klass->has_references.
13283                  */
13284                 klass->has_references |= klass->parent->has_references;
13285         } else {
13286                 klass->instance_size = sizeof (MonoObject);
13287                 klass->min_align = 1;
13288         }
13289
13290         /* FIXME: handle packing_size and instance_size */
13291         typebuilder_setup_fields (klass, &error);
13292         if (!mono_error_ok (&error))
13293                 goto failure;
13294         typebuilder_setup_properties (klass, &error);
13295         if (!mono_error_ok (&error))
13296                 goto failure;
13297
13298         typebuilder_setup_events (klass, &error);
13299         if (!mono_error_ok (&error))
13300                 goto failure;
13301
13302         klass->wastypebuilder = TRUE;
13303
13304         /* 
13305          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13306          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13307          * we want to return normal System.MonoType objects, so clear these out from the cache.
13308          *
13309          * Together with this we must ensure the contents of all instances to match the created type.
13310          */
13311         if (domain->type_hash && klass->generic_container) {
13312                 struct remove_instantiations_user_data data;
13313                 data.klass = klass;
13314                 data.error = &error;
13315                 mono_error_assert_ok (&error);
13316                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13317                 if (!is_ok (&error))
13318                         goto failure;
13319         }
13320
13321         mono_domain_unlock (domain);
13322         mono_loader_unlock ();
13323
13324         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13325                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13326                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13327                 goto failure_unlocked;
13328         }
13329
13330         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13331         if (!is_ok (&error))
13332                 goto failure_unlocked;
13333
13334         g_assert (res != (MonoReflectionType*)tb);
13335
13336         return res;
13337
13338 failure:
13339         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13340         klass->wastypebuilder = TRUE;
13341         mono_domain_unlock (domain);
13342         mono_loader_unlock ();
13343 failure_unlocked:
13344         mono_error_set_pending_exception (&error);
13345         return NULL;
13346 }
13347
13348 static gboolean
13349 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13350 {
13351         MonoGenericParamFull *param;
13352         MonoImage *image;
13353         MonoClass *pklass;
13354
13355         mono_error_init (error);
13356
13357         image = &gparam->tbuilder->module->dynamic_image->image;
13358
13359         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13360
13361         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13362         mono_error_assert_ok (error);
13363         param->param.num = gparam->index;
13364
13365         if (gparam->mbuilder) {
13366                 if (!gparam->mbuilder->generic_container) {
13367                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13368                         return_val_if_nok (error, FALSE);
13369
13370                         MonoClass *klass = mono_class_from_mono_type (tb);
13371                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13372                         gparam->mbuilder->generic_container->is_method = TRUE;
13373                         /* 
13374                          * Cannot set owner.method, since the MonoMethod is not created yet.
13375                          * Set the image field instead, so type_in_image () works.
13376                          */
13377                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13378                         gparam->mbuilder->generic_container->owner.image = klass->image;
13379                 }
13380                 param->param.owner = gparam->mbuilder->generic_container;
13381         } else if (gparam->tbuilder) {
13382                 if (!gparam->tbuilder->generic_container) {
13383                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13384                         return_val_if_nok (error, FALSE);
13385                         MonoClass *klass = mono_class_from_mono_type (tb);
13386                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13387                         gparam->tbuilder->generic_container->owner.klass = klass;
13388                 }
13389                 param->param.owner = gparam->tbuilder->generic_container;
13390         }
13391
13392         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13393
13394         gparam->type.type = &pklass->byval_arg;
13395
13396         mono_class_set_ref_info (pklass, gparam);
13397         mono_image_append_class_to_reflection_info_set (pklass);
13398
13399         return TRUE;
13400 }
13401
13402 void
13403 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13404 {
13405         MonoError error;
13406         (void) reflection_initialize_generic_parameter (gparam, &error);
13407         mono_error_set_pending_exception (&error);
13408 }
13409
13410
13411 MonoArray *
13412 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13413 {
13414         MonoError error;
13415         MonoReflectionModuleBuilder *module = sig->module;
13416         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13417         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13418         guint32 buflen, i;
13419         MonoArray *result;
13420         SigBuffer buf;
13421
13422         check_array_for_usertypes (sig->arguments, &error);
13423         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13424
13425         sigbuffer_init (&buf, 32);
13426
13427         sigbuffer_add_value (&buf, 0x07);
13428         sigbuffer_add_value (&buf, na);
13429         if (assembly != NULL){
13430                 for (i = 0; i < na; ++i) {
13431                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13432                         encode_reflection_type (assembly, type, &buf, &error);
13433                         if (!is_ok (&error)) goto fail;
13434                 }
13435         }
13436
13437         buflen = buf.p - buf.buf;
13438         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13439         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13440         sigbuffer_free (&buf);
13441         return result;
13442 fail:
13443         sigbuffer_free (&buf);
13444         mono_error_raise_exception (&error); /* FIXME don't raise here */
13445         return NULL;
13446 }
13447
13448 MonoArray *
13449 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13450 {
13451         MonoError error;
13452         MonoDynamicImage *assembly = sig->module->dynamic_image;
13453         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13454         guint32 buflen, i;
13455         MonoArray *result;
13456         SigBuffer buf;
13457
13458         check_array_for_usertypes (sig->arguments, &error);
13459         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13460
13461         sigbuffer_init (&buf, 32);
13462
13463         sigbuffer_add_value (&buf, 0x06);
13464         for (i = 0; i < na; ++i) {
13465                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13466                 encode_reflection_type (assembly, type, &buf, &error);
13467                 if (!is_ok (&error))
13468                         goto fail;
13469         }
13470
13471         buflen = buf.p - buf.buf;
13472         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13473         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13474         sigbuffer_free (&buf);
13475
13476         return result;
13477 fail:
13478         sigbuffer_free (&buf);
13479         mono_error_raise_exception (&error); /* FIXME don't raise here */
13480         return NULL;
13481 }
13482
13483 typedef struct {
13484         MonoMethod *handle;
13485         MonoDomain *domain;
13486 } DynamicMethodReleaseData;
13487
13488 /*
13489  * The runtime automatically clean up those after finalization.
13490 */      
13491 static MonoReferenceQueue *dynamic_method_queue;
13492
13493 static void
13494 free_dynamic_method (void *dynamic_method)
13495 {
13496         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13497         MonoDomain *domain = data->domain;
13498         MonoMethod *method = data->handle;
13499         guint32 dis_link;
13500
13501         mono_domain_lock (domain);
13502         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13503         g_hash_table_remove (domain->method_to_dyn_method, method);
13504         mono_domain_unlock (domain);
13505         g_assert (dis_link);
13506         mono_gchandle_free (dis_link);
13507
13508         mono_runtime_free_method (domain, method);
13509         g_free (data);
13510 }
13511
13512 static gboolean
13513 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13514 {
13515         MonoReferenceQueue *queue;
13516         MonoMethod *handle;
13517         DynamicMethodReleaseData *release_data;
13518         ReflectionMethodBuilder rmb;
13519         MonoMethodSignature *sig;
13520         MonoClass *klass;
13521         MonoDomain *domain;
13522         GSList *l;
13523         int i;
13524
13525         mono_error_init (error);
13526
13527         if (mono_runtime_is_shutting_down ()) {
13528                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13529                 return FALSE;
13530         }
13531
13532         if (!(queue = dynamic_method_queue)) {
13533                 mono_loader_lock ();
13534                 if (!(queue = dynamic_method_queue))
13535                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13536                 mono_loader_unlock ();
13537         }
13538
13539         sig = dynamic_method_to_signature (mb, error);
13540         return_val_if_nok (error, FALSE);
13541
13542         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13543
13544         /*
13545          * Resolve references.
13546          */
13547         /* 
13548          * Every second entry in the refs array is reserved for storing handle_class,
13549          * which is needed by the ldtoken implementation in the JIT.
13550          */
13551         rmb.nrefs = mb->nrefs;
13552         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13553         for (i = 0; i < mb->nrefs; i += 2) {
13554                 MonoClass *handle_class;
13555                 gpointer ref;
13556                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13557
13558                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13559                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13560                         /*
13561                          * The referenced DynamicMethod should already be created by the managed
13562                          * code, except in the case of circular references. In that case, we store
13563                          * method in the refs array, and fix it up later when the referenced 
13564                          * DynamicMethod is created.
13565                          */
13566                         if (method->mhandle) {
13567                                 ref = method->mhandle;
13568                         } else {
13569                                 /* FIXME: GC object stored in unmanaged memory */
13570                                 ref = method;
13571
13572                                 /* FIXME: GC object stored in unmanaged memory */
13573                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13574                         }
13575                         handle_class = mono_defaults.methodhandle_class;
13576                 } else {
13577                         MonoException *ex = NULL;
13578                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13579                         if (!is_ok  (error)) {
13580                                 g_free (rmb.refs);
13581                                 return FALSE;
13582                         }
13583                         if (!ref)
13584                                 ex = mono_get_exception_type_load (NULL, NULL);
13585                         else if (mono_security_core_clr_enabled ())
13586                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13587
13588                         if (ex) {
13589                                 g_free (rmb.refs);
13590                                 mono_error_set_exception_instance (error, ex);
13591                                 return FALSE;
13592                         }
13593                 }
13594
13595                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13596                 rmb.refs [i + 1] = handle_class;
13597         }               
13598
13599         if (mb->owner) {
13600                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13601                 if (!is_ok (error)) {
13602                         g_free (rmb.refs);
13603                         return FALSE;
13604                 }
13605                 klass = mono_class_from_mono_type (owner_type);
13606         } else {
13607                 klass = mono_defaults.object_class;
13608         }
13609
13610         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13611         release_data = g_new (DynamicMethodReleaseData, 1);
13612         release_data->handle = handle;
13613         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13614         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13615                 g_free (release_data);
13616
13617         /* Fix up refs entries pointing at us */
13618         for (l = mb->referenced_by; l; l = l->next) {
13619                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13620                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13621                 gpointer *data;
13622                 
13623                 g_assert (method->mhandle);
13624
13625                 data = (gpointer*)wrapper->method_data;
13626                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13627                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13628                                 data [i + 1] = mb->mhandle;
13629                 }
13630         }
13631         g_slist_free (mb->referenced_by);
13632
13633         g_free (rmb.refs);
13634
13635         /* ilgen is no longer needed */
13636         mb->ilgen = NULL;
13637
13638         domain = mono_domain_get ();
13639         mono_domain_lock (domain);
13640         if (!domain->method_to_dyn_method)
13641                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13642         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13643         mono_domain_unlock (domain);
13644
13645         return TRUE;
13646 }
13647
13648 void
13649 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13650 {
13651         MonoError error;
13652         (void) reflection_create_dynamic_method (mb, &error);
13653         mono_error_set_pending_exception (&error);
13654 }
13655
13656 #endif /* DISABLE_REFLECTION_EMIT */
13657
13658 /**
13659  * 
13660  * mono_reflection_is_valid_dynamic_token:
13661  * 
13662  * Returns TRUE if token is valid.
13663  * 
13664  */
13665 gboolean
13666 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13667 {
13668         return lookup_dyn_token (image, token) != NULL;
13669 }
13670
13671 MonoMethodSignature *
13672 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13673 {
13674         MonoMethodSignature *sig;
13675         g_assert (image_is_dynamic (image));
13676
13677         mono_error_init (error);
13678
13679         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13680         if (sig)
13681                 return sig;
13682
13683         return mono_method_signature_checked (method, error);
13684 }
13685
13686 #ifndef DISABLE_REFLECTION_EMIT
13687
13688 /**
13689  * mono_reflection_lookup_dynamic_token:
13690  *
13691  * Finish the Builder object pointed to by TOKEN and return the corresponding
13692  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13693  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13694  * mapping table.
13695  *
13696  * LOCKING: Take the loader lock
13697  */
13698 gpointer
13699 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13700 {
13701         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13702         MonoObject *obj;
13703         MonoClass *klass;
13704
13705         mono_error_init (error);
13706         
13707         obj = lookup_dyn_token (assembly, token);
13708         if (!obj) {
13709                 if (valid_token)
13710                         g_error ("Could not find required dynamic token 0x%08x", token);
13711                 else {
13712                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13713                         return NULL;
13714                 }
13715         }
13716
13717         if (!handle_class)
13718                 handle_class = &klass;
13719         gpointer result = resolve_object (image, obj, handle_class, context, error);
13720         return result;
13721 }
13722
13723 /*
13724  * ensure_complete_type:
13725  *
13726  *   Ensure that KLASS is completed if it is a dynamic type, or references
13727  * dynamic types.
13728  */
13729 static void
13730 ensure_complete_type (MonoClass *klass, MonoError *error)
13731 {
13732         mono_error_init (error);
13733
13734         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13735                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13736
13737                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13738                 return_if_nok (error);
13739
13740                 // Asserting here could break a lot of code
13741                 //g_assert (klass->wastypebuilder);
13742         }
13743
13744         if (klass->generic_class) {
13745                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13746                 int i;
13747
13748                 for (i = 0; i < inst->type_argc; ++i) {
13749                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13750                         return_if_nok (error);
13751                 }
13752         }
13753 }
13754
13755 static gpointer
13756 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13757 {
13758         gpointer result = NULL;
13759
13760         mono_error_init (error);
13761
13762         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13763                 result = mono_string_intern_checked ((MonoString*)obj, error);
13764                 return_val_if_nok (error, NULL);
13765                 *handle_class = mono_defaults.string_class;
13766                 g_assert (result);
13767         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13768                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13769                 return_val_if_nok (error, NULL);
13770                 MonoClass *mc = mono_class_from_mono_type (type);
13771                 if (!mono_class_init (mc)) {
13772                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13773                         return NULL;
13774                 }
13775
13776                 if (context) {
13777                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13778                         return_val_if_nok (error, NULL);
13779
13780                         result = mono_class_from_mono_type (inflated);
13781                         mono_metadata_free_type (inflated);
13782                 } else {
13783                         result = mono_class_from_mono_type (type);
13784                 }
13785                 *handle_class = mono_defaults.typehandle_class;
13786                 g_assert (result);
13787         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13788                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13789                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13790                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13791                 result = ((MonoReflectionMethod*)obj)->method;
13792                 if (context) {
13793                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13794                         mono_error_assert_ok (error);
13795                 }
13796                 *handle_class = mono_defaults.methodhandle_class;
13797                 g_assert (result);
13798         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13799                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13800                 result = mb->mhandle;
13801                 if (!result) {
13802                         /* Type is not yet created */
13803                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13804
13805                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13806                         return_val_if_nok (error, NULL);
13807
13808                         /*
13809                          * Hopefully this has been filled in by calling CreateType() on the
13810                          * TypeBuilder.
13811                          */
13812                         /*
13813                          * TODO: This won't work if the application finishes another 
13814                          * TypeBuilder instance instead of this one.
13815                          */
13816                         result = mb->mhandle;
13817                 }
13818                 if (context) {
13819                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13820                         mono_error_assert_ok (error);
13821                 }
13822                 *handle_class = mono_defaults.methodhandle_class;
13823         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13824                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13825
13826                 result = cb->mhandle;
13827                 if (!result) {
13828                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13829
13830                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13831                         return_val_if_nok (error, NULL);
13832                         result = cb->mhandle;
13833                 }
13834                 if (context) {
13835                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13836                         mono_error_assert_ok (error);
13837                 }
13838                 *handle_class = mono_defaults.methodhandle_class;
13839         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13840                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13841
13842                 ensure_complete_type (field->parent, error);
13843                 return_val_if_nok (error, NULL);
13844
13845                 if (context) {
13846                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13847                         return_val_if_nok (error, NULL);
13848
13849                         MonoClass *klass = mono_class_from_mono_type (inflated);
13850                         MonoClassField *inflated_field;
13851                         gpointer iter = NULL;
13852                         mono_metadata_free_type (inflated);
13853                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13854                                 if (!strcmp (field->name, inflated_field->name))
13855                                         break;
13856                         }
13857                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13858                         result = inflated_field;
13859                 } else {
13860                         result = field;
13861                 }
13862                 *handle_class = mono_defaults.fieldhandle_class;
13863                 g_assert (result);
13864         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13865                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13866                 result = fb->handle;
13867
13868                 if (!result) {
13869                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13870
13871                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13872                         return_val_if_nok (error, NULL);
13873                         result = fb->handle;
13874                 }
13875
13876                 if (fb->handle && fb->handle->parent->generic_container) {
13877                         MonoClass *klass = fb->handle->parent;
13878                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13879                         return_val_if_nok (error, NULL);
13880
13881                         MonoClass *inflated = mono_class_from_mono_type (type);
13882
13883                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13884                         g_assert (result);
13885                         mono_metadata_free_type (type);
13886                 }
13887                 *handle_class = mono_defaults.fieldhandle_class;
13888         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13889                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13890                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13891                 return_val_if_nok (error, NULL);
13892                 MonoClass *klass;
13893
13894                 klass = type->data.klass;
13895                 if (klass->wastypebuilder) {
13896                         /* Already created */
13897                         result = klass;
13898                 }
13899                 else {
13900                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13901                         return_val_if_nok (error, NULL);
13902                         result = type->data.klass;
13903                         g_assert (result);
13904                 }
13905                 *handle_class = mono_defaults.typehandle_class;
13906         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13907                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13908                 MonoMethodSignature *sig;
13909                 int nargs, i;
13910
13911                 if (helper->arguments)
13912                         nargs = mono_array_length (helper->arguments);
13913                 else
13914                         nargs = 0;
13915
13916                 sig = mono_metadata_signature_alloc (image, nargs);
13917                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13918                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13919
13920                 if (helper->unmanaged_call_conv) { /* unmanaged */
13921                         sig->call_convention = helper->unmanaged_call_conv - 1;
13922                         sig->pinvoke = TRUE;
13923                 } else if (helper->call_conv & 0x02) {
13924                         sig->call_convention = MONO_CALL_VARARG;
13925                 } else {
13926                         sig->call_convention = MONO_CALL_DEFAULT;
13927                 }
13928
13929                 sig->param_count = nargs;
13930                 /* TODO: Copy type ? */
13931                 sig->ret = helper->return_type->type;
13932                 for (i = 0; i < nargs; ++i) {
13933                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13934                         if (!is_ok (error)) {
13935                                 image_g_free (image, sig);
13936                                 return NULL;
13937                         }
13938                 }
13939
13940                 result = sig;
13941                 *handle_class = NULL;
13942         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13943                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13944                 /* Already created by the managed code */
13945                 g_assert (method->mhandle);
13946                 result = method->mhandle;
13947                 *handle_class = mono_defaults.methodhandle_class;
13948         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13949                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13950                 return_val_if_nok (error, NULL);
13951                 type = mono_class_inflate_generic_type_checked (type, context, error);
13952                 return_val_if_nok (error, NULL);
13953
13954                 result = mono_class_from_mono_type (type);
13955                 *handle_class = mono_defaults.typehandle_class;
13956                 g_assert (result);
13957                 mono_metadata_free_type (type);
13958         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13959                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13960                 return_val_if_nok (error, NULL);
13961                 type = mono_class_inflate_generic_type_checked (type, context, error);
13962                 return_val_if_nok (error, NULL);
13963
13964                 result = mono_class_from_mono_type (type);
13965                 *handle_class = mono_defaults.typehandle_class;
13966                 g_assert (result);
13967                 mono_metadata_free_type (type);
13968         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13969                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13970                 MonoClass *inflated;
13971                 MonoType *type;
13972                 MonoClassField *field;
13973
13974                 if (is_sre_field_builder (mono_object_class (f->fb)))
13975                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13976                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13977                         field = ((MonoReflectionField*)f->fb)->field;
13978                 else
13979                         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)));
13980
13981                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13982                 return_val_if_nok (error, NULL);
13983                 type = mono_class_inflate_generic_type_checked (finst, context, error);
13984                 return_val_if_nok (error, NULL);
13985
13986                 inflated = mono_class_from_mono_type (type);
13987
13988                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13989                 ensure_complete_type (field->parent, error);
13990                 if (!is_ok (error)) {
13991                         mono_metadata_free_type (type);
13992                         return NULL;
13993                 }
13994
13995                 g_assert (result);
13996                 mono_metadata_free_type (type);
13997                 *handle_class = mono_defaults.fieldhandle_class;
13998         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13999                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14000                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14001                 return_val_if_nok (error, NULL);
14002                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14003                 return_val_if_nok (error, NULL);
14004
14005                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14006                 MonoMethod *method;
14007
14008                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14009                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14010                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14011                         method = ((MonoReflectionMethod *)c->cb)->method;
14012                 else
14013                         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)));
14014
14015                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14016                 *handle_class = mono_defaults.methodhandle_class;
14017                 mono_metadata_free_type (type);
14018         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14019                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14020                 if (m->method_args) {
14021                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14022                         return_val_if_nok (error, NULL);
14023                         if (context) {
14024                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14025                                 mono_error_assert_ok (error);
14026                         }
14027                 } else {
14028                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14029                         return_val_if_nok (error, NULL);
14030                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14031                         return_val_if_nok (error, NULL);
14032
14033                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14034                         MonoMethod *method;
14035
14036                         if (is_sre_method_builder (mono_object_class (m->mb)))
14037                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14038                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14039                                 method = ((MonoReflectionMethod *)m->mb)->method;
14040                         else
14041                                 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)));
14042
14043                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14044                         mono_metadata_free_type (type);
14045                 }
14046                 *handle_class = mono_defaults.methodhandle_class;
14047         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14048                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14049                 MonoType *mtype;
14050                 MonoClass *klass;
14051                 MonoMethod *method;
14052                 gpointer iter;
14053                 char *name;
14054
14055                 mtype = mono_reflection_type_get_handle (m->parent, error);
14056                 return_val_if_nok (error, NULL);
14057                 klass = mono_class_from_mono_type (mtype);
14058
14059                 /* Find the method */
14060
14061                 name = mono_string_to_utf8 (m->name);
14062                 iter = NULL;
14063                 while ((method = mono_class_get_methods (klass, &iter))) {
14064                         if (!strcmp (method->name, name))
14065                                 break;
14066                 }
14067                 g_free (name);
14068
14069                 // FIXME:
14070                 g_assert (method);
14071                 // FIXME: Check parameters/return value etc. match
14072
14073                 result = method;
14074                 *handle_class = mono_defaults.methodhandle_class;
14075         } else if (is_sre_array (mono_object_get_class(obj)) ||
14076                                 is_sre_byref (mono_object_get_class(obj)) ||
14077                                 is_sre_pointer (mono_object_get_class(obj))) {
14078                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14079                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14080                 return_val_if_nok (error, NULL);
14081
14082                 if (context) {
14083                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14084                         return_val_if_nok (error, NULL);
14085
14086                         result = mono_class_from_mono_type (inflated);
14087                         mono_metadata_free_type (inflated);
14088                 } else {
14089                         result = mono_class_from_mono_type (type);
14090                 }
14091                 *handle_class = mono_defaults.typehandle_class;
14092         } else {
14093                 g_print ("%s\n", obj->vtable->klass->name);
14094                 g_assert_not_reached ();
14095         }
14096         return result;
14097 }
14098
14099 #else /* DISABLE_REFLECTION_EMIT */
14100
14101 MonoArray*
14102 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14103 {
14104         g_assert_not_reached ();
14105         return NULL;
14106 }
14107
14108 void
14109 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14110 {
14111         g_assert_not_reached ();
14112 }
14113
14114 void
14115 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14116 {
14117         g_assert_not_reached ();
14118 }
14119
14120 void
14121 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14122 {
14123         g_assert_not_reached ();
14124 }
14125
14126 void
14127 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14128 {
14129         g_assert_not_reached ();
14130 }
14131
14132 void
14133 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14134 {
14135         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14136 }
14137
14138 void
14139 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14140 {
14141         g_assert_not_reached ();
14142 }
14143
14144 void
14145 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14146 {
14147         g_assert_not_reached ();
14148 }
14149
14150 MonoReflectionModule *
14151 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14152 {
14153         g_assert_not_reached ();
14154         return NULL;
14155 }
14156
14157 guint32
14158 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14159 {
14160         g_assert_not_reached ();
14161         return 0;
14162 }
14163
14164 guint32
14165 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14166 {
14167         g_assert_not_reached ();
14168         return 0;
14169 }
14170
14171 guint32
14172 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14173                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14174 {
14175         g_assert_not_reached ();
14176         return 0;
14177 }
14178
14179 void
14180 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14181 {
14182 }
14183
14184 void
14185 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14186 {
14187         g_assert_not_reached ();
14188 }
14189
14190 void
14191 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14192 {
14193         mono_error_init (error);
14194         *overrides = NULL;
14195         *num_overrides = 0;
14196 }
14197
14198 MonoReflectionEvent *
14199 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14200 {
14201         g_assert_not_reached ();
14202         return NULL;
14203 }
14204
14205 MonoReflectionType*
14206 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14207 {
14208         g_assert_not_reached ();
14209         return NULL;
14210 }
14211
14212 void
14213 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14214 {
14215         g_assert_not_reached ();
14216 }
14217
14218 MonoArray *
14219 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14220 {
14221         g_assert_not_reached ();
14222         return NULL;
14223 }
14224
14225 MonoArray *
14226 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14227 {
14228         g_assert_not_reached ();
14229         return NULL;
14230 }
14231
14232 void 
14233 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14234 {
14235 }
14236
14237 gpointer
14238 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14239 {
14240         return NULL;
14241 }
14242
14243 MonoType*
14244 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14245 {
14246         mono_error_init (error);
14247         if (!ref)
14248                 return NULL;
14249         return ref->type;
14250 }
14251
14252 void
14253 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14254 {
14255         g_assert_not_reached ();
14256 }
14257
14258 #endif /* DISABLE_REFLECTION_EMIT */
14259
14260 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14261 const static guint32 declsec_flags_map[] = {
14262         0x00000000,                                     /* empty */
14263         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14264         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14265         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14266         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14267         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14268         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14269         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14270         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14271         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14272         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14273         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14274         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14275         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14276         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14277         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14278         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14279         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14280         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14281 };
14282
14283 /*
14284  * Returns flags that includes all available security action associated to the handle.
14285  * @token: metadata token (either for a class or a method)
14286  * @image: image where resides the metadata.
14287  */
14288 static guint32
14289 mono_declsec_get_flags (MonoImage *image, guint32 token)
14290 {
14291         int index = mono_metadata_declsec_from_index (image, token);
14292         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14293         guint32 result = 0;
14294         guint32 action;
14295         int i;
14296
14297         /* HasSecurity can be present for other, not specially encoded, attributes,
14298            e.g. SuppressUnmanagedCodeSecurityAttribute */
14299         if (index < 0)
14300                 return 0;
14301
14302         for (i = index; i < t->rows; i++) {
14303                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14304
14305                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14306                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14307                         break;
14308
14309                 action = cols [MONO_DECL_SECURITY_ACTION];
14310                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14311                         result |= declsec_flags_map [action];
14312                 } else {
14313                         g_assert_not_reached ();
14314                 }
14315         }
14316         return result;
14317 }
14318
14319 /*
14320  * Get the security actions (in the form of flags) associated with the specified method.
14321  *
14322  * @method: The method for which we want the declarative security flags.
14323  * Return the declarative security flags for the method (only).
14324  *
14325  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14326  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14327  */
14328 guint32
14329 mono_declsec_flags_from_method (MonoMethod *method)
14330 {
14331         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14332                 /* FIXME: No cache (for the moment) */
14333                 guint32 idx = mono_method_get_index (method);
14334                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14335                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14336                 return mono_declsec_get_flags (method->klass->image, idx);
14337         }
14338         return 0;
14339 }
14340
14341 /*
14342  * Get the security actions (in the form of flags) associated with the specified class.
14343  *
14344  * @klass: The class for which we want the declarative security flags.
14345  * Return the declarative security flags for the class.
14346  *
14347  * Note: We cache the flags inside the MonoClass structure as this will get 
14348  *       called very often (at least for each method).
14349  */
14350 guint32
14351 mono_declsec_flags_from_class (MonoClass *klass)
14352 {
14353         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14354                 if (!klass->ext || !klass->ext->declsec_flags) {
14355                         guint32 idx;
14356
14357                         idx = mono_metadata_token_index (klass->type_token);
14358                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14359                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14360                         mono_loader_lock ();
14361                         mono_class_alloc_ext (klass);
14362                         mono_loader_unlock ();
14363                         /* we cache the flags on classes */
14364                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14365                 }
14366                 return klass->ext->declsec_flags;
14367         }
14368         return 0;
14369 }
14370
14371 /*
14372  * Get the security actions (in the form of flags) associated with the specified assembly.
14373  *
14374  * @assembly: The assembly for which we want the declarative security flags.
14375  * Return the declarative security flags for the assembly.
14376  */
14377 guint32
14378 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14379 {
14380         guint32 idx = 1; /* there is only one assembly */
14381         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14382         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14383         return mono_declsec_get_flags (assembly->image, idx);
14384 }
14385
14386
14387 /*
14388  * Fill actions for the specific index (which may either be an encoded class token or
14389  * an encoded method token) from the metadata image.
14390  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14391  */
14392 static MonoBoolean
14393 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14394         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14395 {
14396         MonoBoolean result = FALSE;
14397         MonoTableInfo *t;
14398         guint32 cols [MONO_DECL_SECURITY_SIZE];
14399         int index = mono_metadata_declsec_from_index (image, token);
14400         int i;
14401
14402         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14403         for (i = index; i < t->rows; i++) {
14404                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14405
14406                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14407                         return result;
14408
14409                 /* if present only replace (class) permissions with method permissions */
14410                 /* if empty accept either class or method permissions */
14411                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14412                         if (!actions->demand.blob) {
14413                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14414                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14415                                 actions->demand.blob = (char*) (blob + 2);
14416                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14417                                 result = TRUE;
14418                         }
14419                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14420                         if (!actions->noncasdemand.blob) {
14421                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14422                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14423                                 actions->noncasdemand.blob = (char*) (blob + 2);
14424                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14425                                 result = TRUE;
14426                         }
14427                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14428                         if (!actions->demandchoice.blob) {
14429                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14430                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14431                                 actions->demandchoice.blob = (char*) (blob + 2);
14432                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14433                                 result = TRUE;
14434                         }
14435                 }
14436         }
14437
14438         return result;
14439 }
14440
14441 static MonoBoolean
14442 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14443         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14444 {
14445         guint32 idx = mono_metadata_token_index (klass->type_token);
14446         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14447         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14448         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14449 }
14450
14451 static MonoBoolean
14452 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14453         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14454 {
14455         guint32 idx = mono_method_get_index (method);
14456         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14457         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14458         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14459 }
14460
14461 /*
14462  * Collect all actions (that requires to generate code in mini) assigned for
14463  * the specified method.
14464  * Note: Don't use the content of actions if the function return FALSE.
14465  */
14466 MonoBoolean
14467 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14468 {
14469         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14470                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14471         MonoBoolean result = FALSE;
14472         guint32 flags;
14473
14474         /* quick exit if no declarative security is present in the metadata */
14475         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14476                 return FALSE;
14477
14478         /* we want the original as the wrapper is "free" of the security informations */
14479         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14480                 method = mono_marshal_method_from_wrapper (method);
14481                 if (!method)
14482                         return FALSE;
14483         }
14484
14485         /* First we look for method-level attributes */
14486         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14487                 mono_class_init (method->klass);
14488                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14489
14490                 result = mono_declsec_get_method_demands_params (method, demands, 
14491                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14492         }
14493
14494         /* Here we use (or create) the class declarative cache to look for demands */
14495         flags = mono_declsec_flags_from_class (method->klass);
14496         if (flags & mask) {
14497                 if (!result) {
14498                         mono_class_init (method->klass);
14499                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14500                 }
14501                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14502                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14503         }
14504
14505         /* The boolean return value is used as a shortcut in case nothing needs to
14506            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14507         return result;
14508 }
14509
14510
14511 /*
14512  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14513  *
14514  * Note: Don't use the content of actions if the function return FALSE.
14515  */
14516 MonoBoolean
14517 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14518 {
14519         MonoBoolean result = FALSE;
14520         guint32 flags;
14521
14522         /* quick exit if no declarative security is present in the metadata */
14523         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14524                 return FALSE;
14525
14526         /* we want the original as the wrapper is "free" of the security informations */
14527         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14528                 method = mono_marshal_method_from_wrapper (method);
14529                 if (!method)
14530                         return FALSE;
14531         }
14532
14533         /* results are independant - zeroize both */
14534         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14535         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14536
14537         /* First we look for method-level attributes */
14538         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14539                 mono_class_init (method->klass);
14540
14541                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14542                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14543         }
14544
14545         /* Here we use (or create) the class declarative cache to look for demands */
14546         flags = mono_declsec_flags_from_class (method->klass);
14547         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14548                 mono_class_init (method->klass);
14549
14550                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14551                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14552         }
14553
14554         return result;
14555 }
14556
14557 /*
14558  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14559  *
14560  * @klass       The inherited class - this is the class that provides the security check (attributes)
14561  * @demans      
14562  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14563  * 
14564  * Note: Don't use the content of actions if the function return FALSE.
14565  */
14566 MonoBoolean
14567 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14568 {
14569         MonoBoolean result = FALSE;
14570         guint32 flags;
14571
14572         /* quick exit if no declarative security is present in the metadata */
14573         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14574                 return FALSE;
14575
14576         /* Here we use (or create) the class declarative cache to look for demands */
14577         flags = mono_declsec_flags_from_class (klass);
14578         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14579                 mono_class_init (klass);
14580                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14581
14582                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14583                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14584         }
14585
14586         return result;
14587 }
14588
14589 /*
14590  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14591  *
14592  * Note: Don't use the content of actions if the function return FALSE.
14593  */
14594 MonoBoolean
14595 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14596 {
14597         /* quick exit if no declarative security is present in the metadata */
14598         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14599                 return FALSE;
14600
14601         /* we want the original as the wrapper is "free" of the security informations */
14602         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14603                 method = mono_marshal_method_from_wrapper (method);
14604                 if (!method)
14605                         return FALSE;
14606         }
14607
14608         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14609                 mono_class_init (method->klass);
14610                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14611
14612                 return mono_declsec_get_method_demands_params (method, demands, 
14613                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14614         }
14615         return FALSE;
14616 }
14617
14618
14619 static MonoBoolean
14620 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14621 {
14622         guint32 cols [MONO_DECL_SECURITY_SIZE];
14623         MonoTableInfo *t;
14624         int i;
14625
14626         int index = mono_metadata_declsec_from_index (image, token);
14627         if (index == -1)
14628                 return FALSE;
14629
14630         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14631         for (i = index; i < t->rows; i++) {
14632                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14633
14634                 /* shortcut - index are ordered */
14635                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14636                         return FALSE;
14637
14638                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14639                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14640                         entry->blob = (char*) (metadata + 2);
14641                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14642                         return TRUE;
14643                 }
14644         }
14645
14646         return FALSE;
14647 }
14648
14649 MonoBoolean
14650 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14651 {
14652         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14653                 guint32 idx = mono_method_get_index (method);
14654                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14655                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14656                 return get_declsec_action (method->klass->image, idx, action, entry);
14657         }
14658         return FALSE;
14659 }
14660
14661 MonoBoolean
14662 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14663 {
14664         /* use cache */
14665         guint32 flags = mono_declsec_flags_from_class (klass);
14666         if (declsec_flags_map [action] & flags) {
14667                 guint32 idx = mono_metadata_token_index (klass->type_token);
14668                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14669                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14670                 return get_declsec_action (klass->image, idx, action, entry);
14671         }
14672         return FALSE;
14673 }
14674
14675 MonoBoolean
14676 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14677 {
14678         guint32 idx = 1; /* there is only one assembly */
14679         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14680         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14681
14682         return get_declsec_action (assembly->image, idx, action, entry);
14683 }
14684
14685 gboolean
14686 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14687 {
14688         MonoObject *res, *exc;
14689         void *params [1];
14690         static MonoMethod *method = NULL;
14691
14692         mono_error_init (error);
14693
14694         if (method == NULL) {
14695                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14696                 g_assert (method);
14697         }
14698
14699         /* 
14700          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14701          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14702          */
14703         g_assert (mono_class_get_ref_info (klass));
14704         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14705
14706         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14707         return_val_if_nok (error, FALSE);
14708
14709         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14710
14711         if (exc || !mono_error_ok (error)) {
14712                 mono_error_cleanup (error);
14713                 return FALSE;
14714         } else
14715                 return *(MonoBoolean*)mono_object_unbox (res);
14716 }
14717
14718 /**
14719  * mono_reflection_type_get_type:
14720  * @reftype: the System.Type object
14721  *
14722  * Returns the MonoType* associated with the C# System.Type object @reftype.
14723  */
14724 MonoType*
14725 mono_reflection_type_get_type (MonoReflectionType *reftype)
14726 {
14727         g_assert (reftype);
14728
14729         MonoError error;
14730         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14731         mono_error_assert_ok (&error);
14732         return result;
14733 }
14734
14735 /**
14736  * mono_reflection_assembly_get_assembly:
14737  * @refassembly: the System.Reflection.Assembly object
14738  *
14739  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14740  */
14741 MonoAssembly*
14742 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14743 {
14744         g_assert (refassembly);
14745
14746         return refassembly->assembly;
14747 }
14748