Merge pull request #2850 from madewokherd/inetpton
[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, MonoError *error);
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, error);
2066         return_val_if_nok (error, 0);
2067
2068         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2069         return_val_if_nok (error, 0);
2070         klass = mono_class_from_mono_type (type);
2071
2072         sigbuffer_init (&buf, 32);
2073         
2074         sigbuffer_add_value (&buf, 0x06);
2075         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2076         if (!is_ok (error))
2077                 goto fail;
2078         /* encode custom attributes before the type */
2079
2080         if (klass->generic_container)
2081                 typespec = create_typespec (assembly, type);
2082
2083         if (typespec) {
2084                 MonoGenericClass *gclass;
2085                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2086                 encode_generic_class (assembly, gclass, &buf);
2087         } else {
2088                 encode_type (assembly, type, &buf);
2089         }
2090         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2091         sigbuffer_free (&buf);
2092         return idx;
2093 fail:
2094         sigbuffer_free (&buf);
2095         return 0;
2096 }
2097
2098 static guint32
2099 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2100 {
2101         MONO_REQ_GC_UNSAFE_MODE;
2102
2103         char blob_size [64];
2104         char *b = blob_size;
2105         char *box_val;
2106         char* buf;
2107         guint32 idx = 0, len = 0, dummy = 0;
2108
2109         buf = (char *)g_malloc (64);
2110         if (!val) {
2111                 *ret_type = MONO_TYPE_CLASS;
2112                 len = 4;
2113                 box_val = (char*)&dummy;
2114         } else {
2115                 box_val = ((char*)val) + sizeof (MonoObject);
2116                 *ret_type = val->vtable->klass->byval_arg.type;
2117         }
2118 handle_enum:
2119         switch (*ret_type) {
2120         case MONO_TYPE_BOOLEAN:
2121         case MONO_TYPE_U1:
2122         case MONO_TYPE_I1:
2123                 len = 1;
2124                 break;
2125         case MONO_TYPE_CHAR:
2126         case MONO_TYPE_U2:
2127         case MONO_TYPE_I2:
2128                 len = 2;
2129                 break;
2130         case MONO_TYPE_U4:
2131         case MONO_TYPE_I4:
2132         case MONO_TYPE_R4:
2133                 len = 4;
2134                 break;
2135         case MONO_TYPE_U8:
2136         case MONO_TYPE_I8:
2137                 len = 8;
2138                 break;
2139         case MONO_TYPE_R8:
2140                 len = 8;
2141                 break;
2142         case MONO_TYPE_VALUETYPE: {
2143                 MonoClass *klass = val->vtable->klass;
2144                 
2145                 if (klass->enumtype) {
2146                         *ret_type = mono_class_enum_basetype (klass)->type;
2147                         goto handle_enum;
2148                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2149                         len = 8;
2150                 } else 
2151                         g_error ("we can't encode valuetypes, we should have never reached this line");
2152                 break;
2153         }
2154         case MONO_TYPE_CLASS:
2155                 break;
2156         case MONO_TYPE_STRING: {
2157                 MonoString *str = (MonoString*)val;
2158                 /* there is no signature */
2159                 len = str->length * 2;
2160                 mono_metadata_encode_value (len, b, &b);
2161 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2162                 {
2163                         char *swapped = g_malloc (2 * mono_string_length (str));
2164                         const char *p = (const char*)mono_string_chars (str);
2165
2166                         swap_with_size (swapped, p, 2, mono_string_length (str));
2167                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2168                         g_free (swapped);
2169                 }
2170 #else
2171                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2172 #endif
2173
2174                 g_free (buf);
2175                 return idx;
2176         }
2177         case MONO_TYPE_GENERICINST:
2178                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2179                 goto handle_enum;
2180         default:
2181                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2182         }
2183
2184         /* there is no signature */
2185         mono_metadata_encode_value (len, b, &b);
2186 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2187         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2188         swap_with_size (blob_size, box_val, len, 1);
2189         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2190 #else
2191         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2192 #endif
2193
2194         g_free (buf);
2195         return idx;
2196 }
2197
2198 static guint32
2199 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2200 {
2201         MONO_REQ_GC_UNSAFE_MODE;
2202
2203         mono_error_init (error);
2204
2205         char *str;
2206         SigBuffer buf;
2207         guint32 idx, len;
2208
2209         sigbuffer_init (&buf, 32);
2210
2211         sigbuffer_add_value (&buf, minfo->type);
2212
2213         switch (minfo->type) {
2214         case MONO_NATIVE_BYVALTSTR:
2215         case MONO_NATIVE_BYVALARRAY:
2216                 sigbuffer_add_value (&buf, minfo->count);
2217                 break;
2218         case MONO_NATIVE_LPARRAY:
2219                 if (minfo->eltype || minfo->has_size) {
2220                         sigbuffer_add_value (&buf, minfo->eltype);
2221                         if (minfo->has_size) {
2222                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2223                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2224
2225                                 /* LAMESPEC: ElemMult is undocumented */
2226                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2227                         }
2228                 }
2229                 break;
2230         case MONO_NATIVE_SAFEARRAY:
2231                 if (minfo->eltype)
2232                         sigbuffer_add_value (&buf, minfo->eltype);
2233                 break;
2234         case MONO_NATIVE_CUSTOM:
2235                 if (minfo->guid) {
2236                         str = mono_string_to_utf8 (minfo->guid);
2237                         len = strlen (str);
2238                         sigbuffer_add_value (&buf, len);
2239                         sigbuffer_add_mem (&buf, str, len);
2240                         g_free (str);
2241                 } else {
2242                         sigbuffer_add_value (&buf, 0);
2243                 }
2244                 /* native type name */
2245                 sigbuffer_add_value (&buf, 0);
2246                 /* custom marshaler type name */
2247                 if (minfo->marshaltype || minfo->marshaltyperef) {
2248                         if (minfo->marshaltyperef) {
2249                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2250                                 if (!is_ok (error)) {
2251                                         sigbuffer_free (&buf);
2252                                         return 0;
2253                                 }
2254                                 str = type_get_fully_qualified_name (marshaltype);
2255                         } else
2256                                 str = mono_string_to_utf8 (minfo->marshaltype);
2257                         len = strlen (str);
2258                         sigbuffer_add_value (&buf, len);
2259                         sigbuffer_add_mem (&buf, str, len);
2260                         g_free (str);
2261                 } else {
2262                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2263                         sigbuffer_add_value (&buf, 0);
2264                 }
2265                 if (minfo->mcookie) {
2266                         str = mono_string_to_utf8 (minfo->mcookie);
2267                         len = strlen (str);
2268                         sigbuffer_add_value (&buf, len);
2269                         sigbuffer_add_mem (&buf, str, len);
2270                         g_free (str);
2271                 } else {
2272                         sigbuffer_add_value (&buf, 0);
2273                 }
2274                 break;
2275         default:
2276                 break;
2277         }
2278         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2279         sigbuffer_free (&buf);
2280         return idx;
2281 }
2282
2283 static void
2284 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2285 {
2286         MONO_REQ_GC_UNSAFE_MODE;
2287
2288         mono_error_init (error);
2289
2290         MonoDynamicTable *table;
2291         guint32 *values;
2292
2293         /* maybe this fixup should be done in the C# code */
2294         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2295                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2296         table = &assembly->tables [MONO_TABLE_FIELD];
2297         fb->table_idx = table->next_idx ++;
2298         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2299         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2300         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2301         values [MONO_FIELD_FLAGS] = fb->attrs;
2302         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2303         return_if_nok (error);
2304
2305
2306         if (fb->offset != -1) {
2307                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2308                 table->rows ++;
2309                 alloc_table (table, table->rows);
2310                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2311                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2312                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2313         }
2314         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2315                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2316                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2317                 table->rows ++;
2318                 alloc_table (table, table->rows);
2319                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2320                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2321                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2322                 values [MONO_CONSTANT_TYPE] = field_type;
2323                 values [MONO_CONSTANT_PADDING] = 0;
2324         }
2325         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2326                 guint32 rva_idx;
2327                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2328                 table->rows ++;
2329                 alloc_table (table, table->rows);
2330                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2331                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2332                 /*
2333                  * We store it in the code section because it's simpler for now.
2334                  */
2335                 if (fb->rva_data) {
2336                         if (mono_array_length (fb->rva_data) >= 10)
2337                                 stream_data_align (&assembly->code);
2338                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2339                 } else
2340                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2341                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2342         }
2343         if (fb->marshal_info) {
2344                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2345                 table->rows ++;
2346                 alloc_table (table, table->rows);
2347                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2348                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2349                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2350                 return_if_nok (error);
2351         }
2352 }
2353
2354 static guint32
2355 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2356 {
2357         MONO_REQ_GC_UNSAFE_MODE;
2358
2359         mono_error_init (error);
2360
2361         SigBuffer buf;
2362         guint32 nparams = 0;
2363         MonoReflectionMethodBuilder *mb = fb->get_method;
2364         MonoReflectionMethodBuilder *smb = fb->set_method;
2365         guint32 idx, i;
2366
2367         if (mb && mb->parameters)
2368                 nparams = mono_array_length (mb->parameters);
2369         if (!mb && smb && smb->parameters)
2370                 nparams = mono_array_length (smb->parameters) - 1;
2371         sigbuffer_init (&buf, 32);
2372         if (fb->call_conv & 0x20)
2373                 sigbuffer_add_byte (&buf, 0x28);
2374         else
2375                 sigbuffer_add_byte (&buf, 0x08);
2376         sigbuffer_add_value (&buf, nparams);
2377         if (mb) {
2378                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2379                 if (!is_ok (error))
2380                         goto fail;
2381                 for (i = 0; i < nparams; ++i) {
2382                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2383                         encode_reflection_type (assembly, pt, &buf, error);
2384                         if (!is_ok (error))
2385                                 goto fail;
2386                 }
2387         } else if (smb && smb->parameters) {
2388                 /* the property type is the last param */
2389                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2390                 if (!is_ok (error))
2391                         goto fail;
2392
2393                 for (i = 0; i < nparams; ++i) {
2394                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2395                         encode_reflection_type (assembly, pt, &buf, error);
2396                         if (!is_ok (error))
2397                                 goto fail;
2398                 }
2399         } else {
2400                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2401                 if (!is_ok (error))
2402                         goto fail;
2403         }
2404
2405         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2406         sigbuffer_free (&buf);
2407         return idx;
2408 fail:
2409         sigbuffer_free (&buf);
2410         return 0;
2411 }
2412
2413 static void
2414 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2415 {
2416         MONO_REQ_GC_UNSAFE_MODE;
2417
2418         mono_error_init (error);
2419
2420         MonoDynamicTable *table;
2421         guint32 *values;
2422         guint num_methods = 0;
2423         guint32 semaidx;
2424
2425         /* 
2426          * we need to set things in the following tables:
2427          * PROPERTYMAP (info already filled in _get_type_info ())
2428          * PROPERTY    (rows already preallocated in _get_type_info ())
2429          * METHOD      (method info already done with the generic method code)
2430          * METHODSEMANTICS
2431          * CONSTANT
2432          */
2433         table = &assembly->tables [MONO_TABLE_PROPERTY];
2434         pb->table_idx = table->next_idx ++;
2435         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2436         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2437         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2438         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2439         return_if_nok (error);
2440
2441
2442         /* FIXME: we still don't handle 'other' methods */
2443         if (pb->get_method) num_methods ++;
2444         if (pb->set_method) num_methods ++;
2445
2446         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2447         table->rows += num_methods;
2448         alloc_table (table, table->rows);
2449
2450         if (pb->get_method) {
2451                 semaidx = table->next_idx ++;
2452                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2453                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2454                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2455                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2456         }
2457         if (pb->set_method) {
2458                 semaidx = table->next_idx ++;
2459                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2460                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2461                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2462                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2463         }
2464         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2465                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2466                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2467                 table->rows ++;
2468                 alloc_table (table, table->rows);
2469                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2470                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2471                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2472                 values [MONO_CONSTANT_TYPE] = field_type;
2473                 values [MONO_CONSTANT_PADDING] = 0;
2474         }
2475 }
2476
2477 static void
2478 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2479 {
2480         MONO_REQ_GC_UNSAFE_MODE;
2481
2482         MonoDynamicTable *table;
2483         guint32 *values;
2484         guint num_methods = 0;
2485         guint32 semaidx;
2486
2487         /* 
2488          * we need to set things in the following tables:
2489          * EVENTMAP (info already filled in _get_type_info ())
2490          * EVENT    (rows already preallocated in _get_type_info ())
2491          * METHOD      (method info already done with the generic method code)
2492          * METHODSEMANTICS
2493          */
2494         table = &assembly->tables [MONO_TABLE_EVENT];
2495         eb->table_idx = table->next_idx ++;
2496         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2497         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2498         values [MONO_EVENT_FLAGS] = eb->attrs;
2499         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2500         return_if_nok (error);
2501         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2502
2503         /*
2504          * FIXME: we still don't handle 'other' methods 
2505          */
2506         if (eb->add_method) num_methods ++;
2507         if (eb->remove_method) num_methods ++;
2508         if (eb->raise_method) num_methods ++;
2509
2510         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2511         table->rows += num_methods;
2512         alloc_table (table, table->rows);
2513
2514         if (eb->add_method) {
2515                 semaidx = table->next_idx ++;
2516                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2517                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2518                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2519                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2520         }
2521         if (eb->remove_method) {
2522                 semaidx = table->next_idx ++;
2523                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2524                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2525                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2526                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2527         }
2528         if (eb->raise_method) {
2529                 semaidx = table->next_idx ++;
2530                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2531                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2532                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2533                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2534         }
2535 }
2536
2537 static void
2538 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2539 {
2540         MONO_REQ_GC_UNSAFE_MODE;
2541
2542         mono_error_init (error);
2543
2544         MonoDynamicTable *table;
2545         guint32 num_constraints, i;
2546         guint32 *values;
2547         guint32 table_idx;
2548
2549         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2550         num_constraints = gparam->iface_constraints ?
2551                 mono_array_length (gparam->iface_constraints) : 0;
2552         table->rows += num_constraints;
2553         if (gparam->base_type)
2554                 table->rows++;
2555         alloc_table (table, table->rows);
2556
2557         if (gparam->base_type) {
2558                 table_idx = table->next_idx ++;
2559                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2560
2561                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2562                 return_if_nok (error);
2563                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2564                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2565         }
2566
2567         for (i = 0; i < num_constraints; i++) {
2568                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2569                         gparam->iface_constraints, gpointer, i);
2570
2571                 table_idx = table->next_idx ++;
2572                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2573
2574                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2575                 return_if_nok (error);
2576
2577                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2578                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2579         }
2580 }
2581
2582 static void
2583 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2584 {
2585         MONO_REQ_GC_UNSAFE_MODE;
2586
2587         GenericParamTableEntry *entry;
2588
2589         /*
2590          * The GenericParam table must be sorted according to the `owner' field.
2591          * We need to do this sorting prior to writing the GenericParamConstraint
2592          * table, since we have to use the final GenericParam table indices there
2593          * and they must also be sorted.
2594          */
2595
2596         entry = g_new0 (GenericParamTableEntry, 1);
2597         entry->owner = owner;
2598         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2599         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2600         entry->gparam = gparam;
2601         
2602         g_ptr_array_add (assembly->gen_params, entry);
2603 }
2604
2605 static gboolean
2606 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2607 {
2608         MONO_REQ_GC_UNSAFE_MODE;
2609
2610         MonoDynamicTable *table;
2611         MonoGenericParam *param;
2612         guint32 *values;
2613         guint32 table_idx;
2614
2615         mono_error_init (error);
2616
2617         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2618         table_idx = table->next_idx ++;
2619         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2620
2621         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2622         return_val_if_nok (error, FALSE);
2623
2624         param = gparam_type->data.generic_param;
2625
2626         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2627         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2628         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2629         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2630
2631         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2632                 return FALSE;
2633
2634         encode_constraints (entry->gparam, table_idx, assembly, error);
2635         return_val_if_nok (error, FALSE);
2636
2637         return TRUE;
2638 }
2639
2640 static guint32
2641 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2642 {
2643         MONO_REQ_GC_UNSAFE_MODE;
2644
2645         MonoDynamicTable *table;
2646         guint32 token;
2647         guint32 *values;
2648         guint32 cols [MONO_ASSEMBLY_SIZE];
2649         const char *pubkey;
2650         guint32 publen;
2651
2652         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2653                 return token;
2654
2655         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2656                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2657                 token = table->next_idx ++;
2658                 table->rows ++;
2659                 alloc_table (table, table->rows);
2660                 values = table->values + token * MONO_MODULEREF_SIZE;
2661                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2662
2663                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2664                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2665                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2666
2667                 return token;
2668         }
2669         
2670         if (assembly_is_dynamic (image->assembly))
2671                 /* FIXME: */
2672                 memset (cols, 0, sizeof (cols));
2673         else {
2674                 /* image->assembly->image is the manifest module */
2675                 image = image->assembly->image;
2676                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2677         }
2678
2679         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2680         token = table->next_idx ++;
2681         table->rows ++;
2682         alloc_table (table, table->rows);
2683         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2684         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2685         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2686         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2687         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2688         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2689         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2690         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2691         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2692
2693         if (strcmp ("", image->assembly->aname.culture)) {
2694                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2695                                 image->assembly->aname.culture);
2696         }
2697
2698         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2699                 guchar pubtoken [9];
2700                 pubtoken [0] = 8;
2701                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2702                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2703         } else {
2704                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2705         }
2706         token <<= MONO_RESOLUTION_SCOPE_BITS;
2707         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2708         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2709         return token;
2710 }
2711
2712 static guint32
2713 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2714 {
2715         MONO_REQ_GC_NEUTRAL_MODE;
2716
2717         MonoDynamicTable *table;
2718         guint32 *values;
2719         guint32 token;
2720         SigBuffer buf;
2721
2722         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2723                 return token;
2724
2725         sigbuffer_init (&buf, 32);
2726         switch (type->type) {
2727         case MONO_TYPE_FNPTR:
2728         case MONO_TYPE_PTR:
2729         case MONO_TYPE_SZARRAY:
2730         case MONO_TYPE_ARRAY:
2731         case MONO_TYPE_VAR:
2732         case MONO_TYPE_MVAR:
2733         case MONO_TYPE_GENERICINST:
2734                 encode_type (assembly, type, &buf);
2735                 break;
2736         case MONO_TYPE_CLASS:
2737         case MONO_TYPE_VALUETYPE: {
2738                 MonoClass *k = mono_class_from_mono_type (type);
2739                 if (!k || !k->generic_container) {
2740                         sigbuffer_free (&buf);
2741                         return 0;
2742                 }
2743                 encode_type (assembly, type, &buf);
2744                 break;
2745         }
2746         default:
2747                 sigbuffer_free (&buf);
2748                 return 0;
2749         }
2750
2751         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2752         if (assembly->save) {
2753                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2754                 alloc_table (table, table->rows + 1);
2755                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2756                 values [MONO_TYPESPEC_SIGNATURE] = token;
2757         }
2758         sigbuffer_free (&buf);
2759
2760         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2761         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2762         table->next_idx ++;
2763         return token;
2764 }
2765
2766 static guint32
2767 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2768 {
2769         MONO_REQ_GC_UNSAFE_MODE;
2770
2771         MonoDynamicTable *table;
2772         guint32 *values;
2773         guint32 token, scope, enclosing;
2774         MonoClass *klass;
2775
2776         /* if the type requires a typespec, we must try that first*/
2777         if (try_typespec && (token = create_typespec (assembly, type)))
2778                 return token;
2779         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2780         if (token)
2781                 return token;
2782         klass = mono_class_from_mono_type (type);
2783         if (!klass)
2784                 klass = mono_class_from_mono_type (type);
2785
2786         /*
2787          * If it's in the same module and not a generic type parameter:
2788          */
2789         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2790                         (type->type != MONO_TYPE_MVAR)) {
2791                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2792                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2793                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2794                 return token;
2795         }
2796
2797         if (klass->nested_in) {
2798                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2799                 /* get the typeref idx of the enclosing type */
2800                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2801                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2802         } else {
2803                 scope = resolution_scope_from_image (assembly, klass->image);
2804         }
2805         table = &assembly->tables [MONO_TABLE_TYPEREF];
2806         if (assembly->save) {
2807                 alloc_table (table, table->rows + 1);
2808                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2809                 values [MONO_TYPEREF_SCOPE] = scope;
2810                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2811                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2812         }
2813         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2814         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2815         table->next_idx ++;
2816         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2817         return token;
2818 }
2819
2820 /*
2821  * Despite the name, we handle also TypeSpec (with the above helper).
2822  */
2823 static guint32
2824 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2825 {
2826         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2827 }
2828
2829 #ifndef DISABLE_REFLECTION_EMIT
2830 static guint32
2831 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2832 {
2833         MONO_REQ_GC_NEUTRAL_MODE;
2834
2835         MonoDynamicTable *table;
2836         guint32 *values;
2837         guint32 token, pclass;
2838
2839         switch (parent & MONO_TYPEDEFORREF_MASK) {
2840         case MONO_TYPEDEFORREF_TYPEREF:
2841                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2842                 break;
2843         case MONO_TYPEDEFORREF_TYPESPEC:
2844                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2845                 break;
2846         case MONO_TYPEDEFORREF_TYPEDEF:
2847                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2848                 break;
2849         default:
2850                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2851                 return 0;
2852         }
2853         /* extract the index */
2854         parent >>= MONO_TYPEDEFORREF_BITS;
2855
2856         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2857
2858         if (assembly->save) {
2859                 alloc_table (table, table->rows + 1);
2860                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2861                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2862                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2863                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2864         }
2865
2866         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2867         table->next_idx ++;
2868
2869         return token;
2870 }
2871
2872 /*
2873  * Insert a memberef row into the metadata: the token that point to the memberref
2874  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2875  * mono_image_get_fieldref_token()).
2876  * The sig param is an index to an already built signature.
2877  */
2878 static guint32
2879 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2880 {
2881         MONO_REQ_GC_NEUTRAL_MODE;
2882
2883         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2884         return mono_image_add_memberef_row (assembly, parent, name, sig);
2885 }
2886
2887
2888 static guint32
2889 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2890 {
2891         MONO_REQ_GC_NEUTRAL_MODE;
2892
2893         guint32 token;
2894         MonoMethodSignature *sig;
2895         
2896         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2897
2898         if (create_typespec) {
2899                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2900                 if (token)
2901                         return token;
2902         } 
2903
2904         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2905         if (token && !create_typespec)
2906                 return token;
2907
2908         g_assert (!method->is_inflated);
2909         if (!token) {
2910                 /*
2911                  * A methodref signature can't contain an unmanaged calling convention.
2912                  */
2913                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2914                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2915                         sig->call_convention = MONO_CALL_DEFAULT;
2916                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2917                         method->name,  method_encode_signature (assembly, sig));
2918                 g_free (sig);
2919                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2920         }
2921
2922         if (create_typespec) {
2923                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2924                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2925                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2926
2927                 if (assembly->save) {
2928                         guint32 *values;
2929
2930                         alloc_table (table, table->rows + 1);
2931                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2932                         values [MONO_METHODSPEC_METHOD] = token;
2933                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2934                 }
2935
2936                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2937                 table->next_idx ++;
2938                 /*methodspec and memberef tokens are diferent, */
2939                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2940                 return token;
2941         }
2942         return token;
2943 }
2944
2945 static guint32
2946 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2947 {
2948         guint32 token, parent, sig;
2949         ReflectionMethodBuilder rmb;
2950         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2951         
2952         mono_error_init (error);
2953         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2954         if (token)
2955                 return token;
2956
2957         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2958                 return 0;
2959
2960         /*
2961          * A methodref signature can't contain an unmanaged calling convention.
2962          * Since some flags are encoded as part of call_conv, we need to check against it.
2963         */
2964         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2965                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2966
2967         sig = method_builder_encode_signature (assembly, &rmb, error);
2968         return_val_if_nok (error, 0);
2969
2970         if (tb->generic_params) {
2971                 parent = create_generic_typespec (assembly, tb, error);
2972                 return_val_if_nok (error, 0);
2973         } else {
2974                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2975                 return_val_if_nok (error, 0);
2976
2977                 parent = mono_image_typedef_or_ref (assembly, t);
2978         }
2979
2980         char *name = mono_string_to_utf8 (method->name);
2981
2982         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2983         g_free (name);
2984
2985         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2986
2987         return token;
2988 }
2989
2990 static guint32
2991 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2992                                      const gchar *name, guint32 sig)
2993 {
2994         MonoDynamicTable *table;
2995         guint32 token;
2996         guint32 *values;
2997         
2998         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2999
3000         if (assembly->save) {
3001                 alloc_table (table, table->rows + 1);
3002                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3003                 values [MONO_MEMBERREF_CLASS] = original;
3004                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3005                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3006         }
3007
3008         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3009         table->next_idx ++;
3010
3011         return token;
3012 }
3013
3014 static guint32
3015 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3016 {
3017         SigBuffer buf;
3018         int i;
3019         guint32 nparams = mono_array_length (mb->generic_params);
3020         guint32 idx;
3021
3022         if (!assembly->save)
3023                 return 0;
3024
3025         sigbuffer_init (&buf, 32);
3026
3027         sigbuffer_add_value (&buf, 0xa);
3028         sigbuffer_add_value (&buf, nparams);
3029
3030         for (i = 0; i < nparams; i++) {
3031                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3032                 sigbuffer_add_value (&buf, i);
3033         }
3034
3035         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3036         sigbuffer_free (&buf);
3037         return idx;
3038 }
3039
3040 static guint32
3041 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3042 {
3043         MonoDynamicTable *table;
3044         guint32 *values;
3045         guint32 token, mtoken = 0;
3046
3047         mono_error_init (error);
3048         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3049         if (token)
3050                 return token;
3051
3052         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3053
3054         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3055         if (!mono_error_ok (error))
3056                 return 0;
3057
3058         switch (mono_metadata_token_table (mtoken)) {
3059         case MONO_TABLE_MEMBERREF:
3060                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3061                 break;
3062         case MONO_TABLE_METHOD:
3063                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3064                 break;
3065         default:
3066                 g_assert_not_reached ();
3067         }
3068
3069         if (assembly->save) {
3070                 alloc_table (table, table->rows + 1);
3071                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3072                 values [MONO_METHODSPEC_METHOD] = mtoken;
3073                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3074         }
3075
3076         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3077         table->next_idx ++;
3078
3079         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3080         return token;
3081 }
3082
3083 static guint32
3084 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3085 {
3086         guint32 token;
3087
3088         mono_error_init (error);
3089
3090         if (mb->generic_params && create_methodspec) 
3091                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3092
3093         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3094         if (token)
3095                 return token;
3096
3097         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3098         if (!mono_error_ok (error))
3099                 return 0;
3100         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3101         return token;
3102 }
3103
3104 static guint32
3105 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3106 {
3107         guint32 token, parent, sig;
3108         ReflectionMethodBuilder rmb;
3109         char *name;
3110         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3111         
3112         mono_error_init (error);
3113         
3114         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3115         if (token)
3116                 return token;
3117
3118         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3119                 return 0;
3120
3121         if (tb->generic_params) {
3122                 parent = create_generic_typespec (assembly, tb, error);
3123                 return_val_if_nok (error, 0);
3124         } else {
3125                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3126                 return_val_if_nok (error, 0);
3127                 parent = mono_image_typedef_or_ref (assembly, type);
3128         }
3129         
3130         name = mono_string_to_utf8 (rmb.name);
3131         sig = method_builder_encode_signature (assembly, &rmb, error);
3132         return_val_if_nok (error, 0);
3133
3134         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3135
3136         g_free (name);
3137         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3138         return token;
3139 }
3140 #endif
3141
3142 static gboolean
3143 is_field_on_inst (MonoClassField *field)
3144 {
3145         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3146 }
3147
3148 /*
3149  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3150  */
3151 static MonoType*
3152 get_field_on_inst_generic_type (MonoClassField *field)
3153 {
3154         MonoClass *klass, *gtd;
3155         MonoDynamicGenericClass *dgclass;
3156         int field_index;
3157
3158         g_assert (is_field_on_inst (field));
3159
3160         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3161
3162         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3163                 field_index = field - dgclass->fields;
3164                 return dgclass->field_generic_types [field_index];              
3165         }
3166
3167         klass = field->parent;
3168         gtd = klass->generic_class->container_class;
3169
3170         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3171                 field_index = field - klass->fields;
3172                 return gtd->fields [field_index].type;
3173         }
3174
3175         g_assert_not_reached ();
3176         return 0;
3177 }
3178
3179 #ifndef DISABLE_REFLECTION_EMIT
3180 static guint32
3181 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3182 {
3183         MonoType *type;
3184         guint32 token;
3185
3186         g_assert (field);
3187         g_assert (field->parent);
3188
3189         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3190         if (token)
3191                 return token;
3192
3193         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3194                 int index = field - field->parent->fields;
3195                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3196         } else {
3197                 if (is_field_on_inst (field))
3198                         type = get_field_on_inst_generic_type (field);
3199                 else
3200                         type = mono_field_get_type (field);
3201         }
3202         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3203                                                                                         mono_field_get_name (field),
3204                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3205         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3206         return token;
3207 }
3208
3209 static guint32
3210 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3211 {
3212         guint32 token;
3213         MonoClass *klass;
3214         MonoGenericClass *gclass;
3215         MonoType *type;
3216         char *name;
3217
3218         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3219         if (token)
3220                 return token;
3221         if (is_sre_field_builder (mono_object_class (f->fb))) {
3222                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3223                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3224                 return_val_if_nok (error, 0);
3225                 klass = mono_class_from_mono_type (type);
3226                 gclass = type->data.generic_class;
3227                 g_assert (gclass->is_dynamic);
3228
3229                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3230                 return_val_if_nok (error, 0);
3231                 name = mono_string_to_utf8 (fb->name);
3232                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3233                 g_free (name);          
3234         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3235                 guint32 sig;
3236                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3237
3238                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3239                 return_val_if_nok (error, 0);
3240                 klass = mono_class_from_mono_type (type);
3241
3242                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3243                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3244         } else {
3245                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3246                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3247         }
3248
3249         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3250         return token;
3251 }
3252
3253 static guint32
3254 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3255 {
3256         guint32 sig, token;
3257         MonoClass *klass;
3258         MonoGenericClass *gclass;
3259         MonoType *type;
3260
3261         mono_error_init (error);
3262
3263         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3264
3265         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3266         if (token)
3267                 return token;
3268
3269         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3270                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3271                 ReflectionMethodBuilder rmb;
3272                 char *name;
3273
3274                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3275                 return_val_if_nok (error, 0);
3276                 klass = mono_class_from_mono_type (type);
3277
3278                 gclass = type->data.generic_class;
3279                 g_assert (gclass->is_dynamic);
3280
3281                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3282                         return 0;
3283
3284                 sig = method_builder_encode_signature (assembly, &rmb, error);
3285                 return_val_if_nok (error, 0);
3286
3287                 name = mono_string_to_utf8 (rmb.name);
3288
3289                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3290                 g_free (name);
3291         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3292                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3293
3294                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3295                 return_val_if_nok (error, 0);
3296                 klass = mono_class_from_mono_type (type);
3297
3298                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3299                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3300         } else {
3301                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3302                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3303         }
3304
3305
3306         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3307         return token;
3308 }
3309
3310 static MonoMethod*
3311 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3312 {
3313         MonoClass *klass;
3314         MonoGenericContext tmp_context;
3315         MonoType **type_argv;
3316         MonoGenericInst *ginst;
3317         MonoMethod *method, *inflated;
3318         int count, i;
3319
3320         mono_error_init (error);
3321
3322         init_type_builder_generics ((MonoObject*)m->inst, error);
3323         return_val_if_nok (error, NULL);
3324
3325         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3326         return_val_if_nok (error, NULL);
3327
3328         klass = method->klass;
3329
3330         if (m->method_args == NULL)
3331                 return method;
3332
3333         if (method->is_inflated)
3334                 method = ((MonoMethodInflated *) method)->declaring;
3335
3336         count = mono_array_length (m->method_args);
3337
3338         type_argv = g_new0 (MonoType *, count);
3339         for (i = 0; i < count; i++) {
3340                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3341                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3342                 return_val_if_nok (error, NULL);
3343         }
3344         ginst = mono_metadata_get_generic_inst (count, type_argv);
3345         g_free (type_argv);
3346
3347         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3348         tmp_context.method_inst = ginst;
3349
3350         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3351         mono_error_assert_ok (error);
3352         return inflated;
3353 }
3354
3355 static guint32
3356 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3357 {
3358         guint32 sig, token = 0;
3359         MonoType *type;
3360         MonoClass *klass;
3361
3362         mono_error_init (error);
3363
3364         if (m->method_args) {
3365                 MonoMethod *inflated;
3366
3367                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3368                 return_val_if_nok (error, 0);
3369
3370                 if (create_methodspec)
3371                         token = mono_image_get_methodspec_token (assembly, inflated);
3372                 else
3373                         token = mono_image_get_inflated_method_token (assembly, inflated);
3374                 return token;
3375         }
3376
3377         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3378         if (token)
3379                 return token;
3380
3381         if (is_sre_method_builder (mono_object_class (m->mb))) {
3382                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3383                 MonoGenericClass *gclass;
3384                 ReflectionMethodBuilder rmb;
3385                 char *name;
3386
3387                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3388                 return_val_if_nok (error, 0);
3389                 klass = mono_class_from_mono_type (type);
3390                 gclass = type->data.generic_class;
3391                 g_assert (gclass->is_dynamic);
3392
3393                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3394                         return 0;
3395
3396                 sig = method_builder_encode_signature (assembly, &rmb, error);
3397                 return_val_if_nok (error, 0);
3398
3399                 name = mono_string_to_utf8 (rmb.name);
3400
3401                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3402                 g_free (name);          
3403         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3404                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3405
3406                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3407                 return_val_if_nok (error, 0);
3408                 klass = mono_class_from_mono_type (type);
3409
3410                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3411                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3412         } else {
3413                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3414                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3415         }
3416
3417         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3418         return token;
3419 }
3420
3421 static guint32
3422 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3423 {
3424         SigBuffer buf;
3425         int i;
3426         guint32 nparams = context->method_inst->type_argc;
3427         guint32 idx;
3428
3429         if (!assembly->save)
3430                 return 0;
3431
3432         sigbuffer_init (&buf, 32);
3433         /*
3434          * FIXME: vararg, explicit_this, differenc call_conv values...
3435          */
3436         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3437         sigbuffer_add_value (&buf, nparams);
3438
3439         for (i = 0; i < nparams; i++)
3440                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3441
3442         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3443         sigbuffer_free (&buf);
3444         return idx;
3445 }
3446
3447 static guint32
3448 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3449 {
3450         MonoDynamicTable *table;
3451         guint32 *values;
3452         guint32 token, mtoken = 0, sig;
3453         MonoMethodInflated *imethod;
3454         MonoMethod *declaring;
3455
3456         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3457
3458         g_assert (method->is_inflated);
3459         imethod = (MonoMethodInflated *) method;
3460         declaring = imethod->declaring;
3461
3462         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3463         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3464
3465         if (!mono_method_signature (declaring)->generic_param_count)
3466                 return mtoken;
3467
3468         switch (mono_metadata_token_table (mtoken)) {
3469         case MONO_TABLE_MEMBERREF:
3470                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3471                 break;
3472         case MONO_TABLE_METHOD:
3473                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3474                 break;
3475         default:
3476                 g_assert_not_reached ();
3477         }
3478
3479         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3480
3481         if (assembly->save) {
3482                 alloc_table (table, table->rows + 1);
3483                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3484                 values [MONO_METHODSPEC_METHOD] = mtoken;
3485                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3486         }
3487
3488         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3489         table->next_idx ++;
3490
3491         return token;
3492 }
3493
3494 static guint32
3495 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3496 {
3497         MonoMethodInflated *imethod;
3498         guint32 token;
3499         
3500         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3501         if (token)
3502                 return token;
3503
3504         g_assert (method->is_inflated);
3505         imethod = (MonoMethodInflated *) method;
3506
3507         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3508                 token = method_encode_methodspec (assembly, method);
3509         } else {
3510                 guint32 sig = method_encode_signature (
3511                         assembly, mono_method_signature (imethod->declaring));
3512                 token = mono_image_get_memberref_token (
3513                         assembly, &method->klass->byval_arg, method->name, sig);
3514         }
3515
3516         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3517         return token;
3518 }
3519
3520 static guint32
3521 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3522 {
3523         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3524         guint32 sig, token;
3525
3526         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3527         token = mono_image_get_memberref_token (
3528                 assembly, &m->klass->byval_arg, m->name, sig);
3529
3530         return token;
3531 }
3532
3533 static guint32
3534 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3535 {
3536         MonoDynamicTable *table;
3537         MonoClass *klass;
3538         MonoType *type;
3539         guint32 *values;
3540         guint32 token;
3541         SigBuffer buf;
3542         int count, i;
3543
3544         /*
3545          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3546          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3547          * Because of this, we must not insert it into the `typeref' hash table.
3548          */
3549         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3550         return_val_if_nok (error, 0);
3551         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3552         if (token)
3553                 return token;
3554
3555         sigbuffer_init (&buf, 32);
3556
3557         g_assert (tb->generic_params);
3558         klass = mono_class_from_mono_type (type);
3559
3560         if (tb->generic_container) {
3561                 if (!mono_reflection_create_generic_class (tb, error))
3562                         goto fail;
3563         }
3564
3565         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3566         g_assert (klass->generic_container);
3567         sigbuffer_add_value (&buf, klass->byval_arg.type);
3568         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3569
3570         count = mono_array_length (tb->generic_params);
3571         sigbuffer_add_value (&buf, count);
3572         for (i = 0; i < count; i++) {
3573                 MonoReflectionGenericParam *gparam;
3574
3575                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3576                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3577                 if (!is_ok (error))
3578                         goto fail;
3579
3580                 encode_type (assembly, gparam_type, &buf);
3581         }
3582
3583         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3584
3585         if (assembly->save) {
3586                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3587                 alloc_table (table, table->rows + 1);
3588                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3589                 values [MONO_TYPESPEC_SIGNATURE] = token;
3590         }
3591         sigbuffer_free (&buf);
3592
3593         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3594         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3595         table->next_idx ++;
3596         return token;
3597 fail:
3598         sigbuffer_free (&buf);
3599         return 0;
3600 }
3601
3602 /*
3603  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3604  */
3605 static MonoType*
3606 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3607 {
3608         int i, count, len, pos;
3609         MonoType *t;
3610
3611         mono_error_init (error);
3612
3613         count = 0;
3614         if (modreq)
3615                 count += mono_array_length (modreq);
3616         if (modopt)
3617                 count += mono_array_length (modopt);
3618
3619         if (count == 0)
3620                 return mono_metadata_type_dup (NULL, type);
3621
3622         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3623         t = (MonoType *)g_malloc (len);
3624         memcpy (t, type, MONO_SIZEOF_TYPE);
3625
3626         t->num_mods = count;
3627         pos = 0;
3628         if (modreq) {
3629                 for (i = 0; i < mono_array_length (modreq); ++i) {
3630                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3631                         if (!is_ok (error))
3632                                 goto fail;
3633                         t->modifiers [pos].required = 1;
3634                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3635                         pos ++;
3636                 }
3637         }
3638         if (modopt) {
3639                 for (i = 0; i < mono_array_length (modopt); ++i) {
3640                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3641                         if (!is_ok (error))
3642                                 goto fail;
3643                         t->modifiers [pos].required = 0;
3644                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3645                         pos ++;
3646                 }
3647         }
3648
3649         return t;
3650 fail:
3651         g_free (t);
3652         return NULL;
3653 }
3654
3655 static void
3656 init_type_builder_generics (MonoObject *type, MonoError *error)
3657 {
3658         MonoReflectionTypeBuilder *tb;
3659
3660         mono_error_init (error);
3661
3662         if (!is_sre_type_builder(mono_object_class (type)))
3663                 return;
3664         tb = (MonoReflectionTypeBuilder *)type;
3665
3666         if (tb && tb->generic_container)
3667                 mono_reflection_create_generic_class (tb, error);
3668 }
3669
3670 static guint32
3671 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3672 {
3673         MonoDynamicTable *table;
3674         MonoType *custom = NULL, *type;
3675         guint32 *values;
3676         guint32 token, pclass, parent, sig;
3677         gchar *name;
3678
3679         mono_error_init (error);
3680
3681         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3682         if (token)
3683                 return token;
3684
3685         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3686         return_val_if_nok (error, 0);
3687         /* FIXME: is this call necessary? */
3688         mono_class_from_mono_type (typeb);
3689
3690         /*FIXME this is one more layer of ugliness due how types are created.*/
3691         init_type_builder_generics (fb->type, error);
3692         return_val_if_nok (error, 0);
3693
3694         /* fb->type does not include the custom modifiers */
3695         /* FIXME: We should do this in one place when a fieldbuilder is created */
3696         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3697         return_val_if_nok (error, 0);
3698
3699         if (fb->modreq || fb->modopt) {
3700                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3701                 return_val_if_nok (error, 0);
3702         }
3703
3704         sig = fieldref_encode_signature (assembly, NULL, type);
3705         g_free (custom);
3706
3707         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3708         return_val_if_nok (error, 0);
3709         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3710         
3711         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3712         parent >>= MONO_TYPEDEFORREF_BITS;
3713
3714         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3715
3716         name = mono_string_to_utf8 (fb->name);
3717
3718         if (assembly->save) {
3719                 alloc_table (table, table->rows + 1);
3720                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3721                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3722                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3723                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3724         }
3725
3726         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3727         table->next_idx ++;
3728         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3729         g_free (name);
3730         return token;
3731 }
3732
3733 static guint32
3734 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3735 {
3736         SigBuffer buf;
3737         guint32 nargs;
3738         guint32 i, idx;
3739
3740         mono_error_init (error);
3741
3742         if (!assembly->save)
3743                 return 0;
3744
3745         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3746         g_assert (helper->type == 2);
3747
3748         if (helper->arguments)
3749                 nargs = mono_array_length (helper->arguments);
3750         else
3751                 nargs = 0;
3752
3753         sigbuffer_init (&buf, 32);
3754
3755         /* Encode calling convention */
3756         /* Change Any to Standard */
3757         if ((helper->call_conv & 0x03) == 0x03)
3758                 helper->call_conv = 0x01;
3759         /* explicit_this implies has_this */
3760         if (helper->call_conv & 0x40)
3761                 helper->call_conv &= 0x20;
3762
3763         if (helper->call_conv == 0) { /* Unmanaged */
3764                 idx = helper->unmanaged_call_conv - 1;
3765         } else {
3766                 /* Managed */
3767                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3768                 if (helper->call_conv & 0x02) /* varargs */
3769                         idx += 0x05;
3770         }
3771
3772         sigbuffer_add_byte (&buf, idx);
3773         sigbuffer_add_value (&buf, nargs);
3774         encode_reflection_type (assembly, helper->return_type, &buf, error);
3775         if (!is_ok (error))
3776                 goto fail;
3777         for (i = 0; i < nargs; ++i) {
3778                 MonoArray *modreqs = NULL;
3779                 MonoArray *modopts = NULL;
3780                 MonoReflectionType *pt;
3781
3782                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3783                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3784                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3785                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3786
3787                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3788                 if (!is_ok (error))
3789                         goto fail;
3790                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3791                 encode_reflection_type (assembly, pt, &buf, error);
3792                 if (!is_ok (error))
3793                         goto fail;
3794         }
3795         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3796         sigbuffer_free (&buf);
3797
3798         return idx;
3799 fail:
3800         sigbuffer_free (&buf);
3801         return 0;
3802 }
3803
3804 static guint32 
3805 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3806 {
3807         guint32 idx;
3808         MonoDynamicTable *table;
3809         guint32 *values;
3810
3811         mono_error_init (error);
3812
3813         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3814         idx = table->next_idx ++;
3815         table->rows ++;
3816         alloc_table (table, table->rows);
3817         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3818
3819         values [MONO_STAND_ALONE_SIGNATURE] =
3820                 mono_reflection_encode_sighelper (assembly, helper, error);
3821         return_val_if_nok (error, 0);
3822         
3823         return idx;
3824 }
3825
3826 static int
3827 reflection_cc_to_file (int call_conv) {
3828         switch (call_conv & 0x3) {
3829         case 0:
3830         case 1: return MONO_CALL_DEFAULT;
3831         case 2: return MONO_CALL_VARARG;
3832         default:
3833                 g_assert_not_reached ();
3834         }
3835         return 0;
3836 }
3837 #endif /* !DISABLE_REFLECTION_EMIT */
3838
3839 typedef struct {
3840         MonoType *parent;
3841         MonoMethodSignature *sig;
3842         char *name;
3843         guint32 token;
3844 } ArrayMethod;
3845
3846 #ifndef DISABLE_REFLECTION_EMIT
3847 static guint32
3848 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3849 {
3850         guint32 nparams, i;
3851         GList *tmp;
3852         char *name = NULL;
3853         MonoMethodSignature *sig;
3854         ArrayMethod *am = NULL;
3855         MonoType *mtype;
3856
3857         mono_error_init (error);
3858
3859         nparams = mono_array_length (m->parameters);
3860         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3861         sig->hasthis = 1;
3862         sig->sentinelpos = -1;
3863         sig->call_convention = reflection_cc_to_file (m->call_conv);
3864         sig->param_count = nparams;
3865         if (m->ret) {
3866                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3867                 if (!is_ok (error))
3868                         goto fail;
3869         } else
3870                 sig->ret = &mono_defaults.void_class->byval_arg;
3871
3872         mtype = mono_reflection_type_get_handle (m->parent, error);
3873         if (!is_ok (error))
3874                 goto fail;
3875
3876         for (i = 0; i < nparams; ++i) {
3877                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3878                 if (!is_ok (error))
3879                         goto fail;
3880         }
3881
3882         name = mono_string_to_utf8 (m->name);
3883         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3884                 am = (ArrayMethod *)tmp->data;
3885                 if (strcmp (name, am->name) == 0 && 
3886                                 mono_metadata_type_equal (am->parent, mtype) &&
3887                                 mono_metadata_signature_equal (am->sig, sig)) {
3888                         g_free (name);
3889                         g_free (sig);
3890                         m->table_idx = am->token & 0xffffff;
3891                         return am->token;
3892                 }
3893         }
3894         am = g_new0 (ArrayMethod, 1);
3895         am->name = name;
3896         am->sig = sig;
3897         am->parent = mtype;
3898         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3899                 method_encode_signature (assembly, sig));
3900         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3901         m->table_idx = am->token & 0xffffff;
3902         return am->token;
3903 fail:
3904         g_free (am);
3905         g_free (name);
3906         g_free (sig);
3907         return 0;
3908
3909 }
3910
3911 /*
3912  * Insert into the metadata tables all the info about the TypeBuilder tb.
3913  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3914  */
3915 static gboolean
3916 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3917 {
3918         MonoDynamicTable *table;
3919         guint *values;
3920         int i, is_object = 0, is_system = 0;
3921         char *n;
3922
3923         mono_error_init (error);
3924
3925         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3926         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3927         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3928         n = mono_string_to_utf8 (tb->name);
3929         if (strcmp (n, "Object") == 0)
3930                 is_object++;
3931         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3932         g_free (n);
3933         n = mono_string_to_utf8 (tb->nspace);
3934         if (strcmp (n, "System") == 0)
3935                 is_system++;
3936         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3937         g_free (n);
3938         if (tb->parent && !(is_system && is_object) && 
3939                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3940                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3941                 return_val_if_nok (error, FALSE);
3942                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3943         } else {
3944                 values [MONO_TYPEDEF_EXTENDS] = 0;
3945         }
3946         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3947         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3948
3949         /*
3950          * if we have explicitlayout or sequentiallayouts, output data in the
3951          * ClassLayout table.
3952          */
3953         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3954                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3955                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3956                 table->rows++;
3957                 alloc_table (table, table->rows);
3958                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3959                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3960                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3961                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3962         }
3963
3964         /* handle interfaces */
3965         if (tb->interfaces) {
3966                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3967                 i = table->rows;
3968                 table->rows += mono_array_length (tb->interfaces);
3969                 alloc_table (table, table->rows);
3970                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3971                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3972                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3973                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3974                         return_val_if_nok (error, FALSE);
3975                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3976                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3977                         values += MONO_INTERFACEIMPL_SIZE;
3978                 }
3979         }
3980
3981         /* handle fields */
3982         if (tb->fields) {
3983                 table = &assembly->tables [MONO_TABLE_FIELD];
3984                 table->rows += tb->num_fields;
3985                 alloc_table (table, table->rows);
3986                 for (i = 0; i < tb->num_fields; ++i) {
3987                         mono_image_get_field_info (
3988                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3989                         return_val_if_nok (error, FALSE);
3990                 }
3991         }
3992
3993         /* handle constructors */
3994         if (tb->ctors) {
3995                 table = &assembly->tables [MONO_TABLE_METHOD];
3996                 table->rows += mono_array_length (tb->ctors);
3997                 alloc_table (table, table->rows);
3998                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3999                         if (!mono_image_get_ctor_info (domain,
4000                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
4001                                                        assembly, error))
4002                                 return FALSE;
4003                 }
4004         }
4005
4006         /* handle methods */
4007         if (tb->methods) {
4008                 table = &assembly->tables [MONO_TABLE_METHOD];
4009                 table->rows += tb->num_methods;
4010                 alloc_table (table, table->rows);
4011                 for (i = 0; i < tb->num_methods; ++i) {
4012                         if (!mono_image_get_method_info (
4013                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4014                                 return FALSE;
4015                 }
4016         }
4017
4018         /* Do the same with properties etc.. */
4019         if (tb->events && mono_array_length (tb->events)) {
4020                 table = &assembly->tables [MONO_TABLE_EVENT];
4021                 table->rows += mono_array_length (tb->events);
4022                 alloc_table (table, table->rows);
4023                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4024                 table->rows ++;
4025                 alloc_table (table, table->rows);
4026                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4027                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4028                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4029                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4030                         mono_image_get_event_info (
4031                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4032                         return_val_if_nok (error, FALSE);
4033                 }
4034         }
4035         if (tb->properties && mono_array_length (tb->properties)) {
4036                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4037                 table->rows += mono_array_length (tb->properties);
4038                 alloc_table (table, table->rows);
4039                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4040                 table->rows ++;
4041                 alloc_table (table, table->rows);
4042                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4043                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4044                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4045                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4046                         mono_image_get_property_info (
4047                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4048                         return_val_if_nok (error, FALSE);
4049                 }
4050         }
4051
4052         /* handle generic parameters */
4053         if (tb->generic_params) {
4054                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4055                 table->rows += mono_array_length (tb->generic_params);
4056                 alloc_table (table, table->rows);
4057                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4058                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4059
4060                         mono_image_get_generic_param_info (
4061                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4062                 }
4063         }
4064
4065         mono_image_add_decl_security (assembly, 
4066                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4067
4068         if (tb->subtypes) {
4069                 MonoDynamicTable *ntable;
4070                 
4071                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4072                 ntable->rows += mono_array_length (tb->subtypes);
4073                 alloc_table (ntable, ntable->rows);
4074                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4075
4076                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4077                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4078
4079                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4080                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4081                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4082                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4083                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4084                                 ntable->next_idx, ntable->rows);*/
4085                         values += MONO_NESTED_CLASS_SIZE;
4086                         ntable->next_idx++;
4087                 }
4088         }
4089
4090         return TRUE;
4091 }
4092 #endif
4093
4094 static void
4095 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4096 {
4097         int i;
4098
4099         mono_ptr_array_append (*types, type);
4100
4101         if (!type->subtypes)
4102                 return;
4103
4104         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4105                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4106                 collect_types (types, subtype);
4107         }
4108 }
4109
4110 static gint
4111 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4112 {
4113         if ((*type1)->table_idx < (*type2)->table_idx)
4114                 return -1;
4115         else
4116                 if ((*type1)->table_idx > (*type2)->table_idx)
4117                         return 1;
4118         else
4119                 return 0;
4120 }
4121
4122 static gboolean
4123 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4124         int i;
4125
4126         mono_error_init (error);
4127         if (!pinfo)
4128                 return TRUE;
4129         for (i = 0; i < mono_array_length (pinfo); ++i) {
4130                 MonoReflectionParamBuilder *pb;
4131                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4132                 if (!pb)
4133                         continue;
4134                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4135                         return FALSE;
4136         }
4137
4138         return TRUE;
4139 }
4140
4141 static gboolean
4142 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4143         int i;
4144
4145         mono_error_init (error);
4146         
4147         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4148                 return FALSE;
4149         if (tb->fields) {
4150                 for (i = 0; i < tb->num_fields; ++i) {
4151                         MonoReflectionFieldBuilder* fb;
4152                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4153                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4154                                 return FALSE;
4155                 }
4156         }
4157         if (tb->events) {
4158                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4159                         MonoReflectionEventBuilder* eb;
4160                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4161                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4162                                 return FALSE;
4163                 }
4164         }
4165         if (tb->properties) {
4166                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4167                         MonoReflectionPropertyBuilder* pb;
4168                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4169                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4170                                 return FALSE;
4171                 }
4172         }
4173         if (tb->ctors) {
4174                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4175                         MonoReflectionCtorBuilder* cb;
4176                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4177                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4178                             !params_add_cattrs (assembly, cb->pinfo, error))
4179                                 return FALSE;
4180                 }
4181         }
4182
4183         if (tb->methods) {
4184                 for (i = 0; i < tb->num_methods; ++i) {
4185                         MonoReflectionMethodBuilder* mb;
4186                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4187                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4188                             !params_add_cattrs (assembly, mb->pinfo, error))
4189                                 return FALSE;
4190                 }
4191         }
4192
4193         if (tb->subtypes) {
4194                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4195                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4196                                 return FALSE;
4197                 }
4198         }
4199
4200         return TRUE;
4201 }
4202
4203 static gboolean
4204 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4205 {
4206         int i;
4207         
4208         mono_error_init (error);
4209
4210         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4211                 return FALSE;
4212
4213         if (moduleb->global_methods) {
4214                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4215                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4216                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4217                             !params_add_cattrs (assembly, mb->pinfo, error))
4218                                 return FALSE;
4219                 }
4220         }
4221
4222         if (moduleb->global_fields) {
4223                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4224                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4225                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4226                                 return FALSE;
4227                 }
4228         }
4229         
4230         if (moduleb->types) {
4231                 for (i = 0; i < moduleb->num_types; ++i) {
4232                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4233                                 return FALSE;
4234                 }
4235         }
4236
4237         return TRUE;
4238 }
4239
4240 static void
4241 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4242 {
4243         MonoDynamicTable *table;
4244         guint32 *values;
4245         char blob_size [6];
4246         guchar hash [20];
4247         char *b = blob_size;
4248         char *dir, *path;
4249
4250         table = &assembly->tables [MONO_TABLE_FILE];
4251         table->rows++;
4252         alloc_table (table, table->rows);
4253         values = table->values + table->next_idx * MONO_FILE_SIZE;
4254         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4255         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4256         if (image_is_dynamic (module->image)) {
4257                 /* This depends on the fact that the main module is emitted last */
4258                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4259                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4260         } else {
4261                 dir = NULL;
4262                 path = g_strdup (module->image->name);
4263         }
4264         mono_sha1_get_digest_from_file (path, hash);
4265         g_free (dir);
4266         g_free (path);
4267         mono_metadata_encode_value (20, b, &b);
4268         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4269         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4270         table->next_idx ++;
4271 }
4272
4273 static void
4274 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4275 {
4276         MonoDynamicTable *table;
4277         int i;
4278
4279         table = &assembly->tables [MONO_TABLE_MODULE];
4280         mb->table_idx = table->next_idx ++;
4281         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4282         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4283         i /= 16;
4284         ++i;
4285         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4286         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4287         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4288         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4289 }
4290
4291 static guint32
4292 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4293         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4294 {
4295         MonoDynamicTable *table;
4296         guint32 *values;
4297         guint32 visib, res;
4298
4299         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4300         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4301                 return 0;
4302
4303         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4304         table->rows++;
4305         alloc_table (table, table->rows);
4306         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4307
4308         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4309         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4310         if (klass->nested_in)
4311                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4312         else
4313                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4314         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4315         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4316
4317         res = table->next_idx;
4318
4319         table->next_idx ++;
4320
4321         /* Emit nested types */
4322         if (klass->ext && klass->ext->nested_classes) {
4323                 GList *tmp;
4324
4325                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4326                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4327         }
4328
4329         return res;
4330 }
4331
4332 static void
4333 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4334                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4335                               MonoError *error)
4336 {
4337         MonoClass *klass;
4338         guint32 idx, i;
4339
4340         mono_error_init (error);
4341
4342         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4343         return_if_nok (error);
4344
4345         klass = mono_class_from_mono_type (t);
4346
4347         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4348
4349         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4350                                                                                                    parent_index, assembly);
4351
4352         /* 
4353          * Emit nested types
4354          * We need to do this ourselves since klass->nested_classes is not set up.
4355          */
4356         if (tb->subtypes) {
4357                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4358                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4359                         return_if_nok (error);
4360                 }
4361         }
4362 }
4363
4364 static void
4365 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4366         guint32 module_index, MonoDynamicImage *assembly)
4367 {
4368         MonoImage *image = module->image;
4369         MonoTableInfo  *t;
4370         guint32 i;
4371
4372         t = &image->tables [MONO_TABLE_TYPEDEF];
4373
4374         for (i = 0; i < t->rows; ++i) {
4375                 MonoError error;
4376                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4377                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4378
4379                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4380                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4381         }
4382 }
4383
4384 static void
4385 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4386 {
4387         MonoDynamicTable *table;
4388         guint32 *values;
4389         guint32 scope, scope_idx, impl, current_idx;
4390         gboolean forwarder = TRUE;
4391         gpointer iter = NULL;
4392         MonoClass *nested;
4393
4394         if (klass->nested_in) {
4395                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4396                 forwarder = FALSE;
4397         } else {
4398                 scope = resolution_scope_from_image (assembly, klass->image);
4399                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4400                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4401                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4402         }
4403
4404         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4405
4406         table->rows++;
4407         alloc_table (table, table->rows);
4408         current_idx = table->next_idx;
4409         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4410
4411         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4412         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4413         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4414         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4415         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4416
4417         table->next_idx++;
4418
4419         while ((nested = mono_class_get_nested_types (klass, &iter)))
4420                 add_exported_type (assemblyb, assembly, nested, current_idx);
4421 }
4422
4423 static void
4424 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4425 {
4426         MonoError error;
4427         MonoClass *klass;
4428         int i;
4429
4430         if (!assemblyb->type_forwarders)
4431                 return;
4432
4433         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4434                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4435                 MonoType *type;
4436                 if (!t)
4437                         continue;
4438
4439                 type = mono_reflection_type_get_handle (t, &error);
4440                 mono_error_assert_ok (&error);
4441                 g_assert (type);
4442
4443                 klass = mono_class_from_mono_type (type);
4444
4445                 add_exported_type (assemblyb, assembly, klass, 0);
4446         }
4447 }
4448
4449 #define align_pointer(base,p)\
4450         do {\
4451                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4452                 if (__diff & 3)\
4453                         (p) += 4 - (__diff & 3);\
4454         } while (0)
4455
4456 static int
4457 compare_constants (const void *a, const void *b)
4458 {
4459         const guint32 *a_values = (const guint32 *)a;
4460         const guint32 *b_values = (const guint32 *)b;
4461         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4462 }
4463
4464 static int
4465 compare_semantics (const void *a, const void *b)
4466 {
4467         const guint32 *a_values = (const guint32 *)a;
4468         const guint32 *b_values = (const guint32 *)b;
4469         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4470         if (assoc)
4471                 return assoc;
4472         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4473 }
4474
4475 static int
4476 compare_custom_attrs (const void *a, const void *b)
4477 {
4478         const guint32 *a_values = (const guint32 *)a;
4479         const guint32 *b_values = (const guint32 *)b;
4480
4481         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4482 }
4483
4484 static int
4485 compare_field_marshal (const void *a, const void *b)
4486 {
4487         const guint32 *a_values = (const guint32 *)a;
4488         const guint32 *b_values = (const guint32 *)b;
4489
4490         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4491 }
4492
4493 static int
4494 compare_nested (const void *a, const void *b)
4495 {
4496         const guint32 *a_values = (const guint32 *)a;
4497         const guint32 *b_values = (const guint32 *)b;
4498
4499         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4500 }
4501
4502 static int
4503 compare_genericparam (const void *a, const void *b)
4504 {
4505         MonoError error;
4506         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4507         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4508
4509         if ((*b_entry)->owner == (*a_entry)->owner) {
4510                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4511                 mono_error_assert_ok (&error);
4512                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4513                 mono_error_assert_ok (&error);
4514                 return 
4515                         mono_type_get_generic_param_num (a_type) -
4516                         mono_type_get_generic_param_num (b_type);
4517         } else
4518                 return (*a_entry)->owner - (*b_entry)->owner;
4519 }
4520
4521 static int
4522 compare_declsecurity_attrs (const void *a, const void *b)
4523 {
4524         const guint32 *a_values = (const guint32 *)a;
4525         const guint32 *b_values = (const guint32 *)b;
4526
4527         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4528 }
4529
4530 static int
4531 compare_interface_impl (const void *a, const void *b)
4532 {
4533         const guint32 *a_values = (const guint32 *)a;
4534         const guint32 *b_values = (const guint32 *)b;
4535
4536         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4537         if (klass)
4538                 return klass;
4539
4540         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4541 }
4542
4543 static void
4544 pad_heap (MonoDynamicStream *sh)
4545 {
4546         if (sh->index & 3) {
4547                 int sz = 4 - (sh->index & 3);
4548                 memset (sh->data + sh->index, 0, sz);
4549                 sh->index += sz;
4550         }
4551 }
4552
4553 struct StreamDesc {
4554         const char *name;
4555         MonoDynamicStream *stream;
4556 };
4557
4558 /*
4559  * build_compressed_metadata() fills in the blob of data that represents the 
4560  * raw metadata as it will be saved in the PE file. The five streams are output 
4561  * and the metadata tables are comnpressed from the guint32 array representation, 
4562  * to the compressed on-disk format.
4563  */
4564 static gboolean
4565 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4566 {
4567         MonoDynamicTable *table;
4568         int i;
4569         guint64 valid_mask = 0;
4570         guint64 sorted_mask;
4571         guint32 heapt_size = 0;
4572         guint32 meta_size = 256; /* allow for header and other stuff */
4573         guint32 table_offset;
4574         guint32 ntables = 0;
4575         guint64 *int64val;
4576         guint32 *int32val;
4577         guint16 *int16val;
4578         MonoImage *meta;
4579         unsigned char *p;
4580         struct StreamDesc stream_desc [5];
4581
4582         mono_error_init (error);
4583
4584         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4585         for (i = 0; i < assembly->gen_params->len; i++) {
4586                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4587                 if (!write_generic_param_entry (assembly, entry, error))
4588                         return FALSE;
4589         }
4590
4591         stream_desc [0].name  = "#~";
4592         stream_desc [0].stream = &assembly->tstream;
4593         stream_desc [1].name  = "#Strings";
4594         stream_desc [1].stream = &assembly->sheap;
4595         stream_desc [2].name  = "#US";
4596         stream_desc [2].stream = &assembly->us;
4597         stream_desc [3].name  = "#Blob";
4598         stream_desc [3].stream = &assembly->blob;
4599         stream_desc [4].name  = "#GUID";
4600         stream_desc [4].stream = &assembly->guid;
4601         
4602         /* tables that are sorted */
4603         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4604                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4605                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4606                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4607                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4608                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4609                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4610         
4611         /* Compute table sizes */
4612         /* the MonoImage has already been created in mono_image_basic_init() */
4613         meta = &assembly->image;
4614
4615         /* sizes should be multiple of 4 */
4616         pad_heap (&assembly->blob);
4617         pad_heap (&assembly->guid);
4618         pad_heap (&assembly->sheap);
4619         pad_heap (&assembly->us);
4620
4621         /* Setup the info used by compute_sizes () */
4622         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4623         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4624         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4625
4626         meta_size += assembly->blob.index;
4627         meta_size += assembly->guid.index;
4628         meta_size += assembly->sheap.index;
4629         meta_size += assembly->us.index;
4630
4631         for (i=0; i < MONO_TABLE_NUM; ++i)
4632                 meta->tables [i].rows = assembly->tables [i].rows;
4633         
4634         for (i = 0; i < MONO_TABLE_NUM; i++){
4635                 if (meta->tables [i].rows == 0)
4636                         continue;
4637                 valid_mask |= (guint64)1 << i;
4638                 ntables ++;
4639                 meta->tables [i].row_size = mono_metadata_compute_size (
4640                         meta, i, &meta->tables [i].size_bitfield);
4641                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4642         }
4643         heapt_size += 24; /* #~ header size */
4644         heapt_size += ntables * 4;
4645         /* make multiple of 4 */
4646         heapt_size += 3;
4647         heapt_size &= ~3;
4648         meta_size += heapt_size;
4649         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4650         p = (unsigned char*)meta->raw_metadata;
4651         /* the metadata signature */
4652         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4653         /* version numbers and 4 bytes reserved */
4654         int16val = (guint16*)p;
4655         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4656         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4657         p += 8;
4658         /* version string */
4659         int32val = (guint32*)p;
4660         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4661         p += 4;
4662         memcpy (p, meta->version, strlen (meta->version));
4663         p += GUINT32_FROM_LE (*int32val);
4664         align_pointer (meta->raw_metadata, p);
4665         int16val = (guint16*)p;
4666         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4667         *int16val = GUINT16_TO_LE (5); /* number of streams */
4668         p += 4;
4669
4670         /*
4671          * write the stream info.
4672          */
4673         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4674         table_offset += 3; table_offset &= ~3;
4675
4676         assembly->tstream.index = heapt_size;
4677         for (i = 0; i < 5; ++i) {
4678                 int32val = (guint32*)p;
4679                 stream_desc [i].stream->offset = table_offset;
4680                 *int32val++ = GUINT32_TO_LE (table_offset);
4681                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4682                 table_offset += GUINT32_FROM_LE (*int32val);
4683                 table_offset += 3; table_offset &= ~3;
4684                 p += 8;
4685                 strcpy ((char*)p, stream_desc [i].name);
4686                 p += strlen (stream_desc [i].name) + 1;
4687                 align_pointer (meta->raw_metadata, p);
4688         }
4689         /* 
4690          * now copy the data, the table stream header and contents goes first.
4691          */
4692         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4693         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4694         int32val = (guint32*)p;
4695         *int32val = GUINT32_TO_LE (0); /* reserved */
4696         p += 4;
4697
4698         *p++ = 2; /* version */
4699         *p++ = 0;
4700
4701         if (meta->idx_string_wide)
4702                 *p |= 0x01;
4703         if (meta->idx_guid_wide)
4704                 *p |= 0x02;
4705         if (meta->idx_blob_wide)
4706                 *p |= 0x04;
4707         ++p;
4708         *p++ = 1; /* reserved */
4709         int64val = (guint64*)p;
4710         *int64val++ = GUINT64_TO_LE (valid_mask);
4711         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4712         p += 16;
4713         int32val = (guint32*)p;
4714         for (i = 0; i < MONO_TABLE_NUM; i++){
4715                 if (meta->tables [i].rows == 0)
4716                         continue;
4717                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4718         }
4719         p = (unsigned char*)int32val;
4720
4721         /* sort the tables that still need sorting */
4722         table = &assembly->tables [MONO_TABLE_CONSTANT];
4723         if (table->rows)
4724                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4725         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4726         if (table->rows)
4727                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4728         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4729         if (table->rows)
4730                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4731         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4732         if (table->rows)
4733                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4734         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4735         if (table->rows)
4736                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4737         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4738         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4739         if (table->rows)
4740                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4741         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4742         if (table->rows)
4743                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4744
4745         /* compress the tables */
4746         for (i = 0; i < MONO_TABLE_NUM; i++){
4747                 int row, col;
4748                 guint32 *values;
4749                 guint32 bitfield = meta->tables [i].size_bitfield;
4750                 if (!meta->tables [i].rows)
4751                         continue;
4752                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4753                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4754                 meta->tables [i].base = (char*)p;
4755                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4756                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4757                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4758                                 switch (mono_metadata_table_size (bitfield, col)) {
4759                                 case 1:
4760                                         *p++ = values [col];
4761                                         break;
4762                                 case 2:
4763                                         *p++ = values [col] & 0xff;
4764                                         *p++ = (values [col] >> 8) & 0xff;
4765                                         break;
4766                                 case 4:
4767                                         *p++ = values [col] & 0xff;
4768                                         *p++ = (values [col] >> 8) & 0xff;
4769                                         *p++ = (values [col] >> 16) & 0xff;
4770                                         *p++ = (values [col] >> 24) & 0xff;
4771                                         break;
4772                                 default:
4773                                         g_assert_not_reached ();
4774                                 }
4775                         }
4776                 }
4777                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4778         }
4779         
4780         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4781         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4782         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4783         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4784         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4785
4786         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4787
4788         return TRUE;
4789 }
4790
4791 /*
4792  * Some tables in metadata need to be sorted according to some criteria, but
4793  * when methods and fields are first created with reflection, they may be assigned a token
4794  * that doesn't correspond to the final token they will get assigned after the sorting.
4795  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4796  * with the reflection objects that represent them. Once all the tables are set up, the 
4797  * reflection objects will contains the correct table index. fixup_method() will fixup the
4798  * tokens for the method with ILGenerator @ilgen.
4799  */
4800 static void
4801 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4802 {
4803         guint32 code_idx = GPOINTER_TO_UINT (value);
4804         MonoReflectionILTokenInfo *iltoken;
4805         MonoReflectionFieldBuilder *field;
4806         MonoReflectionCtorBuilder *ctor;
4807         MonoReflectionMethodBuilder *method;
4808         MonoReflectionTypeBuilder *tb;
4809         MonoReflectionArrayMethod *am;
4810         guint32 i, idx = 0;
4811         unsigned char *target;
4812
4813         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4814                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4815                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4816                 switch (target [3]) {
4817                 case MONO_TABLE_FIELD:
4818                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4819                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4820                                 idx = field->table_idx;
4821                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4822                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4823                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4824                         } else {
4825                                 g_assert_not_reached ();
4826                         }
4827                         break;
4828                 case MONO_TABLE_METHOD:
4829                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4830                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4831                                 idx = method->table_idx;
4832                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4833                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4834                                 idx = ctor->table_idx;
4835                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4836                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4837                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4838                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4839                         } else {
4840                                 g_assert_not_reached ();
4841                         }
4842                         break;
4843                 case MONO_TABLE_TYPEDEF:
4844                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4845                                 g_assert_not_reached ();
4846                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4847                         idx = tb->table_idx;
4848                         break;
4849                 case MONO_TABLE_MEMBERREF:
4850                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4851                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4852                                 idx = am->table_idx;
4853                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4854                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4855                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4856                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4857                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4858                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4859                                 continue;
4860                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4861                                 continue;
4862                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4863                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4864                                 g_assert (is_field_on_inst (f));
4865                                 continue;
4866                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4867                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4868                                 continue;
4869                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4870                                 continue;
4871                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4872                                 continue;
4873                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4874                                 continue;
4875                         } else {
4876                                 g_assert_not_reached ();
4877                         }
4878                         break;
4879                 case MONO_TABLE_METHODSPEC:
4880                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4881                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4882                                 g_assert (mono_method_signature (m)->generic_param_count);
4883                                 continue;
4884                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4885                                 continue;
4886                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4887                                 continue;
4888                         } else {
4889                                 g_assert_not_reached ();
4890                         }
4891                         break;
4892                 default:
4893                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4894                 }
4895                 target [0] = idx & 0xff;
4896                 target [1] = (idx >> 8) & 0xff;
4897                 target [2] = (idx >> 16) & 0xff;
4898         }
4899 }
4900
4901 /*
4902  * fixup_cattrs:
4903  *
4904  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4905  * value is not known when the table is emitted.
4906  */
4907 static void
4908 fixup_cattrs (MonoDynamicImage *assembly)
4909 {
4910         MonoDynamicTable *table;
4911         guint32 *values;
4912         guint32 type, i, idx, token;
4913         MonoObject *ctor;
4914
4915         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4916
4917         for (i = 0; i < table->rows; ++i) {
4918                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4919
4920                 type = values [MONO_CUSTOM_ATTR_TYPE];
4921                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4922                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4923                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4924                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4925                         g_assert (ctor);
4926
4927                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4928                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4929                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4930                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4931                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4932                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4933                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4934                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4935                         }
4936                 }
4937         }
4938 }
4939
4940 static void
4941 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4942 {
4943         MonoDynamicTable *table;
4944         guint32 *values;
4945
4946         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4947         table->rows++;
4948         alloc_table (table, table->rows);
4949         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4950         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4951         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4952         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4953         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4954         table->next_idx++;
4955 }
4956
4957 static void
4958 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4959 {
4960         MonoDynamicTable *table;
4961         guint32 *values;
4962         char blob_size [6];
4963         guchar hash [20];
4964         char *b = blob_size;
4965         char *name, *sname;
4966         guint32 idx, offset;
4967
4968         if (rsrc->filename) {
4969                 name = mono_string_to_utf8 (rsrc->filename);
4970                 sname = g_path_get_basename (name);
4971         
4972                 table = &assembly->tables [MONO_TABLE_FILE];
4973                 table->rows++;
4974                 alloc_table (table, table->rows);
4975                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4976                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4977                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4978                 g_free (sname);
4979
4980                 mono_sha1_get_digest_from_file (name, hash);
4981                 mono_metadata_encode_value (20, b, &b);
4982                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4983                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4984                 g_free (name);
4985                 idx = table->next_idx++;
4986                 rsrc->offset = 0;
4987                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4988         } else {
4989                 char sizebuf [4];
4990                 char *data;
4991                 guint len;
4992                 if (rsrc->data) {
4993                         data = mono_array_addr (rsrc->data, char, 0);
4994                         len = mono_array_length (rsrc->data);
4995                 } else {
4996                         data = NULL;
4997                         len = 0;
4998                 }
4999                 offset = len;
5000                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
5001                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
5002                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
5003                 mono_image_add_stream_data (&assembly->resources, data, len);
5004
5005                 if (!mb->is_main)
5006                         /* 
5007                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5008                          * the main module, but that needs to reference the FILE table
5009                          * which isn't emitted yet.
5010                          */
5011                         return;
5012                 else
5013                         idx = 0;
5014         }
5015
5016         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5017 }
5018
5019 static void
5020 set_version_from_string (MonoString *version, guint32 *values)
5021 {
5022         gchar *ver, *p, *str;
5023         guint32 i;
5024         
5025         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5026         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5027         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5028         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5029         if (!version)
5030                 return;
5031         ver = str = mono_string_to_utf8 (version);
5032         for (i = 0; i < 4; ++i) {
5033                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5034                 switch (*p) {
5035                 case '.':
5036                         p++;
5037                         break;
5038                 case '*':
5039                         /* handle Revision and Build */
5040                         p++;
5041                         break;
5042                 }
5043                 ver = p;
5044         }
5045         g_free (str);
5046 }
5047
5048 static guint32
5049 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5050         gsize len;
5051         guint32 token = 0;
5052         char blob_size [6];
5053         char *b = blob_size;
5054
5055         if (!pkey)
5056                 return token;
5057
5058         len = mono_array_length (pkey);
5059         mono_metadata_encode_value (len, b, &b);
5060         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5061         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5062
5063         assembly->public_key = (guint8 *)g_malloc (len);
5064         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5065         assembly->public_key_len = len;
5066
5067         /* Special case: check for ECMA key (16 bytes) */
5068         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5069                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5070                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5071         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5072                 /* minimum key size (in 2.0) is 384 bits */
5073                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5074         } else {
5075                 /* FIXME - verifier */
5076                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5077                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5078         }
5079         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5080
5081         return token;
5082 }
5083
5084 static void
5085 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5086 {
5087         MonoDynamicTable *table;
5088         MonoDynamicImage *assembly;
5089         MonoReflectionAssemblyBuilder *assemblyb;
5090         MonoDomain *domain;
5091         guint32 *values;
5092         int i;
5093         guint32 module_index;
5094
5095         mono_error_init (error);
5096
5097         assemblyb = moduleb->assemblyb;
5098         assembly = moduleb->dynamic_image;
5099         domain = mono_object_domain (assemblyb);
5100
5101         /* Emit ASSEMBLY table */
5102         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5103         alloc_table (table, 1);
5104         values = table->values + MONO_ASSEMBLY_SIZE;
5105         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5106         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5107         if (assemblyb->culture) {
5108                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5109         } else {
5110                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5111         }
5112         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5113         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5114         set_version_from_string (assemblyb->version, values);
5115
5116         /* Emit FILE + EXPORTED_TYPE table */
5117         module_index = 0;
5118         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5119                 int j;
5120                 MonoReflectionModuleBuilder *file_module = 
5121                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5122                 if (file_module != moduleb) {
5123                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5124                         module_index ++;
5125                         if (file_module->types) {
5126                                 for (j = 0; j < file_module->num_types; ++j) {
5127                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5128                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5129                                         return_if_nok (error);
5130                                 }
5131                         }
5132                 }
5133         }
5134         if (assemblyb->loaded_modules) {
5135                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5136                         MonoReflectionModule *file_module = 
5137                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5138                         mono_image_fill_file_table (domain, file_module, assembly);
5139                         module_index ++;
5140                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5141                 }
5142         }
5143         if (assemblyb->type_forwarders)
5144                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5145
5146         /* Emit MANIFESTRESOURCE table */
5147         module_index = 0;
5148         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5149                 int j;
5150                 MonoReflectionModuleBuilder *file_module = 
5151                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5152                 /* The table for the main module is emitted later */
5153                 if (file_module != moduleb) {
5154                         module_index ++;
5155                         if (file_module->resources) {
5156                                 int len = mono_array_length (file_module->resources);
5157                                 for (j = 0; j < len; ++j) {
5158                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5159                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5160                                 }
5161                         }
5162                 }
5163         }               
5164 }
5165
5166 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5167
5168 /*
5169  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5170  * for the modulebuilder @moduleb.
5171  * At the end of the process, method and field tokens are fixed up and the 
5172  * on-disk compressed metadata representation is created.
5173  * Return TRUE on success, or FALSE on failure and sets @error
5174  */
5175 gboolean
5176 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5177 {
5178         MonoDynamicTable *table;
5179         MonoDynamicImage *assembly;
5180         MonoReflectionAssemblyBuilder *assemblyb;
5181         MonoDomain *domain;
5182         MonoPtrArray types;
5183         guint32 *values;
5184         int i, j;
5185
5186         mono_error_init (error);
5187
5188         assemblyb = moduleb->assemblyb;
5189         assembly = moduleb->dynamic_image;
5190         domain = mono_object_domain (assemblyb);
5191
5192         if (assembly->text_rva)
5193                 return TRUE;
5194
5195         assembly->text_rva = START_TEXT_RVA;
5196
5197         if (moduleb->is_main) {
5198                 mono_image_emit_manifest (moduleb, error);
5199                 return_val_if_nok (error, FALSE);
5200         }
5201
5202         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5203         table->rows = 1; /* .<Module> */
5204         table->next_idx++;
5205         alloc_table (table, table->rows);
5206         /*
5207          * Set the first entry.
5208          */
5209         values = table->values + table->columns;
5210         values [MONO_TYPEDEF_FLAGS] = 0;
5211         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5212         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5213         values [MONO_TYPEDEF_EXTENDS] = 0;
5214         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5215         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5216
5217         /* 
5218          * handle global methods 
5219          * FIXME: test what to do when global methods are defined in multiple modules.
5220          */
5221         if (moduleb->global_methods) {
5222                 table = &assembly->tables [MONO_TABLE_METHOD];
5223                 table->rows += mono_array_length (moduleb->global_methods);
5224                 alloc_table (table, table->rows);
5225                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5226                         if (!mono_image_get_method_info (
5227                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5228                                 goto leave;
5229                 }
5230         }
5231         if (moduleb->global_fields) {
5232                 table = &assembly->tables [MONO_TABLE_FIELD];
5233                 table->rows += mono_array_length (moduleb->global_fields);
5234                 alloc_table (table, table->rows);
5235                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5236                         mono_image_get_field_info (
5237                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5238                                 error);
5239                         if (!is_ok (error))
5240                                 goto leave;
5241                 }
5242         }
5243
5244         table = &assembly->tables [MONO_TABLE_MODULE];
5245         alloc_table (table, 1);
5246         mono_image_fill_module_table (domain, moduleb, assembly);
5247
5248         /* Collect all types into a list sorted by their table_idx */
5249         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5250
5251         if (moduleb->types)
5252                 for (i = 0; i < moduleb->num_types; ++i) {
5253                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5254                         collect_types (&types, type);
5255                 }
5256
5257         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5258         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5259         table->rows += mono_ptr_array_size (types);
5260         alloc_table (table, table->rows);
5261
5262         /*
5263          * Emit type names + namespaces at one place inside the string heap,
5264          * so load_class_names () needs to touch fewer pages.
5265          */
5266         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5267                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5268                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5269         }
5270         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5271                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5272                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5273         }
5274
5275         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5276                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5277                 if (!mono_image_get_type_info (domain, type, assembly, error))
5278                         goto leave_types;
5279         }
5280
5281         /* 
5282          * table->rows is already set above and in mono_image_fill_module_table.
5283          */
5284         /* add all the custom attributes at the end, once all the indexes are stable */
5285         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5286                 goto leave_types;
5287
5288         /* CAS assembly permissions */
5289         if (assemblyb->permissions_minimum)
5290                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5291         if (assemblyb->permissions_optional)
5292                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5293         if (assemblyb->permissions_refused)
5294                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5295
5296         if (!module_add_cattrs (assembly, moduleb, error))
5297                 goto leave_types;
5298
5299         /* fixup tokens */
5300         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5301
5302         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5303          * the final tokens and don't need another fixup pass. */
5304
5305         if (moduleb->global_methods) {
5306                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5307                         MonoReflectionMethodBuilder *mb = mono_array_get (
5308                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5309                         if (!mono_image_add_methodimpl (assembly, mb, error))
5310                                 goto leave_types;
5311                 }
5312         }
5313
5314         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5315                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5316                 if (type->methods) {
5317                         for (j = 0; j < type->num_methods; ++j) {
5318                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5319                                         type->methods, MonoReflectionMethodBuilder*, j);
5320
5321                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5322                                         goto leave_types;
5323                         }
5324                 }
5325         }
5326
5327         fixup_cattrs (assembly);
5328
5329 leave_types:
5330         mono_ptr_array_destroy (types);
5331 leave:
5332
5333         return mono_error_ok (error);
5334 }
5335
5336 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5337
5338 gboolean
5339 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5340 {
5341         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5342 }
5343
5344 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5345
5346
5347 typedef struct {
5348         guint32 import_lookup_table;
5349         guint32 timestamp;
5350         guint32 forwarder;
5351         guint32 name_rva;
5352         guint32 import_address_table_rva;
5353 } MonoIDT;
5354
5355 typedef struct {
5356         guint32 name_rva;
5357         guint32 flags;
5358 } MonoILT;
5359
5360 #ifndef DISABLE_REFLECTION_EMIT
5361
5362 /*
5363  * mono_image_insert_string:
5364  * @module: module builder object
5365  * @str: a string
5366  *
5367  * Insert @str into the user string stream of @module.
5368  */
5369 guint32
5370 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5371 {
5372         MonoDynamicImage *assembly;
5373         guint32 idx;
5374         char buf [16];
5375         char *b = buf;
5376         
5377         if (!module->dynamic_image)
5378                 mono_image_module_basic_init (module);
5379
5380         assembly = module->dynamic_image;
5381         
5382         if (assembly->save) {
5383                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5384                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5385 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5386         {
5387                 char *swapped = g_malloc (2 * mono_string_length (str));
5388                 const char *p = (const char*)mono_string_chars (str);
5389
5390                 swap_with_size (swapped, p, 2, mono_string_length (str));
5391                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5392                 g_free (swapped);
5393         }
5394 #else
5395                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5396 #endif
5397                 mono_image_add_stream_data (&assembly->us, "", 1);
5398         } else {
5399                 idx = assembly->us.index ++;
5400         }
5401
5402         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5403
5404         return MONO_TOKEN_STRING | idx;
5405 }
5406
5407 guint32
5408 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5409 {
5410         MonoClass *klass;
5411         guint32 token = 0;
5412         MonoMethodSignature *sig;
5413
5414         mono_error_init (error);
5415
5416         klass = obj->vtable->klass;
5417         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5418                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5419                 MonoMethodSignature *old;
5420                 guint32 sig_token, parent;
5421                 int nargs, i;
5422
5423                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5424
5425                 nargs = mono_array_length (opt_param_types);
5426                 old = mono_method_signature (method);
5427                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5428
5429                 sig->hasthis = old->hasthis;
5430                 sig->explicit_this = old->explicit_this;
5431                 sig->call_convention = old->call_convention;
5432                 sig->generic_param_count = old->generic_param_count;
5433                 sig->param_count = old->param_count + nargs;
5434                 sig->sentinelpos = old->param_count;
5435                 sig->ret = old->ret;
5436
5437                 for (i = 0; i < old->param_count; i++)
5438                         sig->params [i] = old->params [i];
5439
5440                 for (i = 0; i < nargs; i++) {
5441                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5442                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5443                         if (!is_ok (error)) goto fail;
5444                 }
5445
5446                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5447                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5448                 parent >>= MONO_TYPEDEFORREF_BITS;
5449
5450                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5451                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5452
5453                 sig_token = method_encode_signature (assembly, sig);
5454                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5455         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5456                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5457                 ReflectionMethodBuilder rmb;
5458                 guint32 parent, sig_token;
5459                 int nopt_args, nparams, ngparams, i;
5460
5461                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5462                         goto fail;
5463                 
5464                 rmb.opt_types = opt_param_types;
5465                 nopt_args = mono_array_length (opt_param_types);
5466
5467                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5468                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5469                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5470
5471                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5472                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5473                 sig->call_convention = rmb.call_conv;
5474                 sig->generic_param_count = ngparams;
5475                 sig->param_count = nparams + nopt_args;
5476                 sig->sentinelpos = nparams;
5477                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5478                 if (!is_ok (error)) goto fail;
5479
5480                 for (i = 0; i < nparams; i++) {
5481                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5482                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5483                         if (!is_ok (error)) goto fail;
5484                 }
5485
5486                 for (i = 0; i < nopt_args; i++) {
5487                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5488                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5489                         if (!is_ok (error)) goto fail;
5490                 }
5491
5492                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5493                 if (!is_ok (error))
5494                         goto fail;
5495
5496                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5497                 if (!mono_error_ok (error))
5498                         goto fail;
5499                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5500
5501                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5502                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5503
5504                 char *name = mono_string_to_utf8 (rmb.name);
5505                 token = mono_image_get_varargs_method_token (
5506                         assembly, parent, name, sig_token);
5507                 g_free (name);
5508         } else {
5509                 g_error ("requested method token for %s\n", klass->name);
5510         }
5511
5512         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5513         register_dyn_token (assembly, token, obj);
5514         return token;
5515 fail:
5516         g_assert (!mono_error_ok (error));
5517         return 0;
5518 }
5519
5520 /*
5521  * mono_image_create_token:
5522  * @assembly: a dynamic assembly
5523  * @obj:
5524  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5525  *
5526  * Get a token to insert in the IL code stream for the given MemberInfo.
5527  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5528  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5529  * entry.
5530  */
5531 guint32
5532 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5533                          gboolean create_open_instance, gboolean register_token,
5534                          MonoError *error)
5535 {
5536         MonoClass *klass;
5537         guint32 token = 0;
5538
5539         mono_error_init (error);
5540
5541         klass = obj->vtable->klass;
5542
5543         /* Check for user defined reflection objects */
5544         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5545         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5546                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5547                 return 0;
5548         }
5549
5550         if (strcmp (klass->name, "MethodBuilder") == 0) {
5551                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5552                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5553
5554                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5555                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5556                 else {
5557                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5558                         if (!mono_error_ok (error))
5559                                 return 0;
5560                 }
5561                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5562         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5563                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5564                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5565
5566                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5567                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5568                 else {
5569                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5570                         if (!mono_error_ok (error))
5571                                 return 0;
5572                 }
5573                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5574         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5575                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5576                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5577                 if (tb->generic_params) {
5578                         token = mono_image_get_generic_field_token (assembly, fb, error);
5579                         return_val_if_nok (error, 0);
5580                 } else {
5581                         if (tb->module->dynamic_image == assembly) {
5582                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5583                         } else {
5584                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5585                         }
5586                 }
5587         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5588                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5589                 if (create_open_instance && tb->generic_params) {
5590                         MonoType *type;
5591                         init_type_builder_generics (obj, error);
5592                         return_val_if_nok (error, 0);
5593                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594                         return_val_if_nok (error, 0);
5595                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5596                         token = mono_metadata_token_from_dor (token);
5597                 } else if (tb->module->dynamic_image == assembly) {
5598                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5599                 } else {
5600                         MonoType *type;
5601                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5602                         return_val_if_nok (error, 0);
5603                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5604                 }
5605         } else if (strcmp (klass->name, "MonoType") == 0) {
5606                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5607                 return_val_if_nok (error, 0);
5608                 MonoClass *mc = mono_class_from_mono_type (type);
5609                 token = mono_metadata_token_from_dor (
5610                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5611         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5612                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5613                 return_val_if_nok (error, 0);
5614                 token = mono_metadata_token_from_dor (
5615                         mono_image_typedef_or_ref (assembly, type));
5616         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5617                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5618                 return_val_if_nok (error, 0);
5619                 token = mono_metadata_token_from_dor (
5620                         mono_image_typedef_or_ref (assembly, type));
5621         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5622                    strcmp (klass->name, "MonoMethod") == 0 ||
5623                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5624                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5625                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5626                 if (m->method->is_inflated) {
5627                         if (create_open_instance)
5628                                 token = mono_image_get_methodspec_token (assembly, m->method);
5629                         else
5630                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5631                 } else if ((m->method->klass->image == &assembly->image) &&
5632                          !m->method->klass->generic_class) {
5633                         static guint32 method_table_idx = 0xffffff;
5634                         if (m->method->klass->wastypebuilder) {
5635                                 /* we use the same token as the one that was assigned
5636                                  * to the Methodbuilder.
5637                                  * FIXME: do the equivalent for Fields.
5638                                  */
5639                                 token = m->method->token;
5640                         } else {
5641                                 /*
5642                                  * Each token should have a unique index, but the indexes are
5643                                  * assigned by managed code, so we don't know about them. An
5644                                  * easy solution is to count backwards...
5645                                  */
5646                                 method_table_idx --;
5647                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5648                         }
5649                 } else {
5650                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5651                 }
5652                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5653         } else if (strcmp (klass->name, "MonoField") == 0) {
5654                 MonoReflectionField *f = (MonoReflectionField *)obj;
5655                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5656                         static guint32 field_table_idx = 0xffffff;
5657                         field_table_idx --;
5658                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5659                 } else {
5660                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5661                 }
5662                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5663         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5664                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5665                 token = mono_image_get_array_token (assembly, m, error);
5666                 return_val_if_nok (error, 0);
5667         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5668                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5669                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5670                 return_val_if_nok (error, 0);
5671         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5672                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5673                 return_val_if_nok (error, 0);
5674                 token = mono_metadata_token_from_dor (
5675                         mono_image_typedef_or_ref (assembly, type));
5676         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5677                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5678                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5679                 return_val_if_nok (error, 0);
5680         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5681                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5682                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5683                 if (!mono_error_ok (error))
5684                         return 0;
5685         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5686                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5687                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5688                 if (!mono_error_ok (error))
5689                         return 0;
5690         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5691                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5692                 return_val_if_nok (error, 0);
5693                 token = mono_metadata_token_from_dor (
5694                                 mono_image_typedef_or_ref (assembly, type));
5695         } else {
5696                 g_error ("requested token for %s\n", klass->name);
5697         }
5698
5699         if (register_token)
5700                 mono_image_register_token (assembly, token, obj);
5701
5702         return token;
5703 }
5704
5705 /*
5706  * mono_image_register_token:
5707  *
5708  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5709  * the Module.ResolveXXXToken () methods to work.
5710  */
5711 void
5712 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5713 {
5714         MonoObject *prev;
5715
5716         dynamic_image_lock (assembly);
5717         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5718         if (prev) {
5719                 /* There could be multiple MethodInfo objects with the same token */
5720                 //g_assert (prev == obj);
5721         } else {
5722                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5723         }
5724         dynamic_image_unlock (assembly);
5725 }
5726
5727 static MonoDynamicImage*
5728 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5729 {
5730         static const guchar entrycode [16] = {0xff, 0x25, 0};
5731         MonoDynamicImage *image;
5732         int i;
5733
5734         const char *version;
5735
5736         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5737                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5738         else
5739                 version = mono_get_runtime_info ()->runtime_version;
5740
5741 #if HAVE_BOEHM_GC
5742         /* The MonoGHashTable's need GC tracking */
5743         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5744 #else
5745         image = g_new0 (MonoDynamicImage, 1);
5746 #endif
5747
5748         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5749         
5750         /*g_print ("created image %p\n", image);*/
5751         /* keep in sync with image.c */
5752         image->image.name = assembly_name;
5753         image->image.assembly_name = image->image.name; /* they may be different */
5754         image->image.module_name = module_name;
5755         image->image.version = g_strdup (version);
5756         image->image.md_version_major = 1;
5757         image->image.md_version_minor = 1;
5758         image->image.dynamic = TRUE;
5759
5760         image->image.references = g_new0 (MonoAssembly*, 1);
5761         image->image.references [0] = NULL;
5762
5763         mono_image_init (&image->image);
5764
5765         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");
5766         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5767         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5768         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5769         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5770         image->handleref = g_hash_table_new (NULL, NULL);
5771         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");
5772         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5773         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");
5774         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");
5775         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5776         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5777         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5778         image->gen_params = g_ptr_array_new ();
5779         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5780
5781         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5782         string_heap_init (&image->sheap);
5783         mono_image_add_stream_data (&image->us, "", 1);
5784         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5785         /* import tables... */
5786         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5787         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5788         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5789         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5790         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5791         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5792         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5793         stream_data_align (&image->code);
5794
5795         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5796
5797         for (i=0; i < MONO_TABLE_NUM; ++i) {
5798                 image->tables [i].next_idx = 1;
5799                 image->tables [i].columns = table_sizes [i];
5800         }
5801
5802         image->image.assembly = (MonoAssembly*)assembly;
5803         image->run = assembly->run;
5804         image->save = assembly->save;
5805         image->pe_kind = 0x1; /* ILOnly */
5806         image->machine = 0x14c; /* I386 */
5807         
5808         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5809
5810         dynamic_images_lock ();
5811
5812         if (!dynamic_images)
5813                 dynamic_images = g_ptr_array_new ();
5814
5815         g_ptr_array_add (dynamic_images, image);
5816
5817         dynamic_images_unlock ();
5818
5819         return image;
5820 }
5821 #endif
5822
5823 static void
5824 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5825 {
5826         g_free (key);
5827 }
5828
5829 static void
5830 release_hashtable (MonoGHashTable **hash)
5831 {
5832         if (*hash) {
5833                 mono_g_hash_table_destroy (*hash);
5834                 *hash = NULL;
5835         }
5836 }
5837
5838 void
5839 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5840 {
5841         release_hashtable (&image->token_fixups);
5842         release_hashtable (&image->handleref_managed);
5843         release_hashtable (&image->tokens);
5844         release_hashtable (&image->remapped_tokens);
5845         release_hashtable (&image->generic_def_objects);
5846         release_hashtable (&image->methodspec);
5847 }
5848
5849 // Free dynamic image pass one: Free resources but not image itself
5850 void
5851 mono_dynamic_image_free (MonoDynamicImage *image)
5852 {
5853         MonoDynamicImage *di = image;
5854         GList *list;
5855         int i;
5856
5857         if (di->methodspec)
5858                 mono_g_hash_table_destroy (di->methodspec);
5859         if (di->typespec)
5860                 g_hash_table_destroy (di->typespec);
5861         if (di->typeref)
5862                 g_hash_table_destroy (di->typeref);
5863         if (di->handleref)
5864                 g_hash_table_destroy (di->handleref);
5865         if (di->handleref_managed)
5866                 mono_g_hash_table_destroy (di->handleref_managed);
5867         if (di->tokens)
5868                 mono_g_hash_table_destroy (di->tokens);
5869         if (di->remapped_tokens)
5870                 mono_g_hash_table_destroy (di->remapped_tokens);
5871         if (di->generic_def_objects)
5872                 mono_g_hash_table_destroy (di->generic_def_objects);
5873         if (di->blob_cache) {
5874                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5875                 g_hash_table_destroy (di->blob_cache);
5876         }
5877         if (di->standalonesig_cache)
5878                 g_hash_table_destroy (di->standalonesig_cache);
5879         for (list = di->array_methods; list; list = list->next) {
5880                 ArrayMethod *am = (ArrayMethod *)list->data;
5881                 g_free (am->sig);
5882                 g_free (am->name);
5883                 g_free (am);
5884         }
5885         g_list_free (di->array_methods);
5886         if (di->gen_params) {
5887                 for (i = 0; i < di->gen_params->len; i++) {
5888                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5889                         mono_gc_deregister_root ((char*) &entry->gparam);
5890                         g_free (entry);
5891                 }
5892                 g_ptr_array_free (di->gen_params, TRUE);
5893         }
5894         if (di->token_fixups)
5895                 mono_g_hash_table_destroy (di->token_fixups);
5896         if (di->method_to_table_idx)
5897                 g_hash_table_destroy (di->method_to_table_idx);
5898         if (di->field_to_table_idx)
5899                 g_hash_table_destroy (di->field_to_table_idx);
5900         if (di->method_aux_hash)
5901                 g_hash_table_destroy (di->method_aux_hash);
5902         if (di->vararg_aux_hash)
5903                 g_hash_table_destroy (di->vararg_aux_hash);
5904         g_free (di->strong_name);
5905         g_free (di->win32_res);
5906         if (di->public_key)
5907                 g_free (di->public_key);
5908
5909         /*g_print ("string heap destroy for image %p\n", di);*/
5910         mono_dynamic_stream_reset (&di->sheap);
5911         mono_dynamic_stream_reset (&di->code);
5912         mono_dynamic_stream_reset (&di->resources);
5913         mono_dynamic_stream_reset (&di->us);
5914         mono_dynamic_stream_reset (&di->blob);
5915         mono_dynamic_stream_reset (&di->tstream);
5916         mono_dynamic_stream_reset (&di->guid);
5917         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5918                 g_free (di->tables [i].values);
5919         }
5920
5921         dynamic_images_lock ();
5922
5923         if (dynamic_images)
5924                 g_ptr_array_remove (dynamic_images, di);
5925
5926         dynamic_images_unlock ();
5927 }
5928
5929 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5930 void
5931 mono_dynamic_image_free_image (MonoDynamicImage *image)
5932 {
5933         /* See create_dynamic_mono_image () */
5934 #if HAVE_BOEHM_GC
5935         /* Allocated using GC_MALLOC */
5936 #else
5937         g_free (image);
5938 #endif
5939 }
5940
5941 #ifndef DISABLE_REFLECTION_EMIT
5942
5943 /*
5944  * mono_image_basic_init:
5945  * @assembly: an assembly builder object
5946  *
5947  * Create the MonoImage that represents the assembly builder and setup some
5948  * of the helper hash table and the basic metadata streams.
5949  */
5950 void
5951 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5952 {
5953         MonoDynamicAssembly *assembly;
5954         MonoDynamicImage *image;
5955         MonoDomain *domain = mono_object_domain (assemblyb);
5956         
5957         if (assemblyb->dynamic_assembly)
5958                 return;
5959
5960 #if HAVE_BOEHM_GC
5961         /* assembly->assembly.image might be GC allocated */
5962         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5963 #else
5964         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5965 #endif
5966
5967         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5968         
5969         assembly->assembly.ref_count = 1;
5970         assembly->assembly.dynamic = TRUE;
5971         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5972         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5973         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5974         if (assemblyb->culture)
5975                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5976         else
5977                 assembly->assembly.aname.culture = g_strdup ("");
5978
5979         if (assemblyb->version) {
5980                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5981                         char **version = g_strsplit (vstr, ".", 4);
5982                         char **parts = version;
5983                         assembly->assembly.aname.major = atoi (*parts++);
5984                         assembly->assembly.aname.minor = atoi (*parts++);
5985                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5986                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5987
5988                         g_strfreev (version);
5989                         g_free (vstr);
5990         } else {
5991                         assembly->assembly.aname.major = 0;
5992                         assembly->assembly.aname.minor = 0;
5993                         assembly->assembly.aname.build = 0;
5994                         assembly->assembly.aname.revision = 0;
5995         }
5996
5997         assembly->run = assemblyb->access != 2;
5998         assembly->save = assemblyb->access != 1;
5999         assembly->domain = domain;
6000
6001         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
6002         image->initial_image = TRUE;
6003         assembly->assembly.aname.name = image->image.name;
6004         assembly->assembly.image = &image->image;
6005         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
6006                 /* -1 to correct for the trailing NULL byte */
6007                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
6008                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6009                 }
6010                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6011         }
6012
6013         mono_domain_assemblies_lock (domain);
6014         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6015         mono_domain_assemblies_unlock (domain);
6016
6017         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6018         
6019         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6020         
6021         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6022 }
6023
6024 #endif /* !DISABLE_REFLECTION_EMIT */
6025
6026 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6027
6028 static int
6029 calc_section_size (MonoDynamicImage *assembly)
6030 {
6031         int nsections = 0;
6032
6033         /* alignment constraints */
6034         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6035         g_assert ((assembly->code.index % 4) == 0);
6036         assembly->meta_size += 3;
6037         assembly->meta_size &= ~3;
6038         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6039         g_assert ((assembly->resources.index % 4) == 0);
6040
6041         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6042         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6043         nsections++;
6044
6045         if (assembly->win32_res) {
6046                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6047
6048                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6049                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6050                 nsections++;
6051         }
6052
6053         assembly->sections [MONO_SECTION_RELOC].size = 12;
6054         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6055         nsections++;
6056
6057         return nsections;
6058 }
6059
6060 typedef struct {
6061         guint32 id;
6062         guint32 offset;
6063         GSList *children;
6064         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6065 } ResTreeNode;
6066
6067 static int
6068 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6069 {
6070         ResTreeNode *t1 = (ResTreeNode*)a;
6071         ResTreeNode *t2 = (ResTreeNode*)b;
6072
6073         return t1->id - t2->id;
6074 }
6075
6076 /*
6077  * resource_tree_create:
6078  *
6079  *  Organize the resources into a resource tree.
6080  */
6081 static ResTreeNode *
6082 resource_tree_create (MonoArray *win32_resources)
6083 {
6084         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6085         GSList *l;
6086         int i;
6087
6088         tree = g_new0 (ResTreeNode, 1);
6089         
6090         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6091                 MonoReflectionWin32Resource *win32_res =
6092                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6093
6094                 /* Create node */
6095
6096                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6097                 lang_node = g_new0 (ResTreeNode, 1);
6098                 lang_node->id = win32_res->lang_id;
6099                 lang_node->win32_res = win32_res;
6100
6101                 /* Create type node if neccesary */
6102                 type_node = NULL;
6103                 for (l = tree->children; l; l = l->next)
6104                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6105                                 type_node = (ResTreeNode*)l->data;
6106                                 break;
6107                         }
6108
6109                 if (!type_node) {
6110                         type_node = g_new0 (ResTreeNode, 1);
6111                         type_node->id = win32_res->res_type;
6112
6113                         /* 
6114                          * The resource types have to be sorted otherwise
6115                          * Windows Explorer can't display the version information.
6116                          */
6117                         tree->children = g_slist_insert_sorted (tree->children, 
6118                                 type_node, resource_tree_compare_by_id);
6119                 }
6120
6121                 /* Create res node if neccesary */
6122                 res_node = NULL;
6123                 for (l = type_node->children; l; l = l->next)
6124                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6125                                 res_node = (ResTreeNode*)l->data;
6126                                 break;
6127                         }
6128
6129                 if (!res_node) {
6130                         res_node = g_new0 (ResTreeNode, 1);
6131                         res_node->id = win32_res->res_id;
6132                         type_node->children = g_slist_append (type_node->children, res_node);
6133                 }
6134
6135                 res_node->children = g_slist_append (res_node->children, lang_node);
6136         }
6137
6138         return tree;
6139 }
6140
6141 /*
6142  * resource_tree_encode:
6143  * 
6144  *   Encode the resource tree into the format used in the PE file.
6145  */
6146 static void
6147 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6148 {
6149         char *entries;
6150         MonoPEResourceDir dir;
6151         MonoPEResourceDirEntry dir_entry;
6152         MonoPEResourceDataEntry data_entry;
6153         GSList *l;
6154         guint32 res_id_entries;
6155
6156         /*
6157          * For the format of the resource directory, see the article
6158          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6159          * Matt Pietrek
6160          */
6161
6162         memset (&dir, 0, sizeof (dir));
6163         memset (&dir_entry, 0, sizeof (dir_entry));
6164         memset (&data_entry, 0, sizeof (data_entry));
6165
6166         g_assert (sizeof (dir) == 16);
6167         g_assert (sizeof (dir_entry) == 8);
6168         g_assert (sizeof (data_entry) == 16);
6169
6170         node->offset = p - begin;
6171
6172         /* IMAGE_RESOURCE_DIRECTORY */
6173         res_id_entries = g_slist_length (node->children);
6174         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6175
6176         memcpy (p, &dir, sizeof (dir));
6177         p += sizeof (dir);
6178
6179         /* Reserve space for entries */
6180         entries = p;
6181         p += sizeof (dir_entry) * res_id_entries;
6182
6183         /* Write children */
6184         for (l = node->children; l; l = l->next) {
6185                 ResTreeNode *child = (ResTreeNode*)l->data;
6186
6187                 if (child->win32_res) {
6188                         guint32 size;
6189
6190                         child->offset = p - begin;
6191
6192                         /* IMAGE_RESOURCE_DATA_ENTRY */
6193                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6194                         size = mono_array_length (child->win32_res->res_data);
6195                         data_entry.rde_size = GUINT32_TO_LE (size);
6196
6197                         memcpy (p, &data_entry, sizeof (data_entry));
6198                         p += sizeof (data_entry);
6199
6200                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6201                         p += size;
6202                 } else {
6203                         resource_tree_encode (child, begin, p, &p);
6204                 }
6205         }
6206
6207         /* IMAGE_RESOURCE_ENTRY */
6208         for (l = node->children; l; l = l->next) {
6209                 ResTreeNode *child = (ResTreeNode*)l->data;
6210
6211                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6212                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6213
6214                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6215                 entries += sizeof (dir_entry);
6216         }
6217
6218         *endbuf = p;
6219 }
6220
6221 static void
6222 resource_tree_free (ResTreeNode * node)
6223 {
6224         GSList * list;
6225         for (list = node->children; list; list = list->next)
6226                 resource_tree_free ((ResTreeNode*)list->data);
6227         g_slist_free(node->children);
6228         g_free (node);
6229 }
6230
6231 static void
6232 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6233 {
6234         char *buf;
6235         char *p;
6236         guint32 size, i;
6237         MonoReflectionWin32Resource *win32_res;
6238         ResTreeNode *tree;
6239
6240         if (!assemblyb->win32_resources)
6241                 return;
6242
6243         /*
6244          * Resources are stored in a three level tree inside the PE file.
6245          * - level one contains a node for each type of resource
6246          * - level two contains a node for each resource
6247          * - level three contains a node for each instance of a resource for a
6248          *   specific language.
6249          */
6250
6251         tree = resource_tree_create (assemblyb->win32_resources);
6252
6253         /* Estimate the size of the encoded tree */
6254         size = 0;
6255         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6256                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6257                 size += mono_array_length (win32_res->res_data);
6258         }
6259         /* Directory structure */
6260         size += mono_array_length (assemblyb->win32_resources) * 256;
6261         p = buf = (char *)g_malloc (size);
6262
6263         resource_tree_encode (tree, p, p, &p);
6264
6265         g_assert (p - buf <= size);
6266
6267         assembly->win32_res = (char *)g_malloc (p - buf);
6268         assembly->win32_res_size = p - buf;
6269         memcpy (assembly->win32_res, buf, p - buf);
6270
6271         g_free (buf);
6272         resource_tree_free (tree);
6273 }
6274
6275 static void
6276 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6277 {
6278         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6279         int i;
6280
6281         p += sizeof (MonoPEResourceDir);
6282         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6283                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6284                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6285                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6286                         fixup_resource_directory (res_section, child, rva);
6287                 } else {
6288                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6289                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6290                 }
6291
6292                 p += sizeof (MonoPEResourceDirEntry);
6293         }
6294 }
6295
6296 static void
6297 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6298 {
6299         guint32 dummy;
6300         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6301                 g_error ("WriteFile returned %d\n", GetLastError ());
6302 }
6303
6304 /*
6305  * mono_image_create_pefile:
6306  * @mb: a module builder object
6307  * 
6308  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6309  * assembly->pefile where it can be easily retrieved later in chunks.
6310  */
6311 gboolean
6312 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6313 {
6314         MonoMSDOSHeader *msdos;
6315         MonoDotNetHeader *header;
6316         MonoSectionTable *section;
6317         MonoCLIHeader *cli_header;
6318         guint32 size, image_size, virtual_base, text_offset;
6319         guint32 header_start, section_start, file_offset, virtual_offset;
6320         MonoDynamicImage *assembly;
6321         MonoReflectionAssemblyBuilder *assemblyb;
6322         MonoDynamicStream pefile_stream = {0};
6323         MonoDynamicStream *pefile = &pefile_stream;
6324         int i, nsections;
6325         guint32 *rva, value;
6326         guchar *p;
6327         static const unsigned char msheader[] = {
6328                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6329                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6330                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6331                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6332                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6333                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6334                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6335                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6336         };
6337
6338         mono_error_init (error);
6339
6340         assemblyb = mb->assemblyb;
6341
6342         mono_image_basic_init (assemblyb);
6343         assembly = mb->dynamic_image;
6344
6345         assembly->pe_kind = assemblyb->pe_kind;
6346         assembly->machine = assemblyb->machine;
6347         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6348         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6349         
6350         if (!mono_image_build_metadata (mb, error))
6351                 return FALSE;
6352         
6353
6354         if (mb->is_main && assemblyb->resources) {
6355                 int len = mono_array_length (assemblyb->resources);
6356                 for (i = 0; i < len; ++i)
6357                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6358         }
6359
6360         if (mb->resources) {
6361                 int len = mono_array_length (mb->resources);
6362                 for (i = 0; i < len; ++i)
6363                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6364         }
6365
6366         if (!build_compressed_metadata (assembly, error))
6367                 return FALSE;
6368
6369         if (mb->is_main)
6370                 assembly_add_win32_resources (assembly, assemblyb);
6371
6372         nsections = calc_section_size (assembly);
6373         
6374         /* The DOS header and stub */
6375         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6376         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6377
6378         /* the dotnet header */
6379         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6380
6381         /* the section tables */
6382         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6383
6384         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6385         virtual_offset = VIRT_ALIGN;
6386         image_size = 0;
6387
6388         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6389                 if (!assembly->sections [i].size)
6390                         continue;
6391                 /* align offsets */
6392                 file_offset += FILE_ALIGN - 1;
6393                 file_offset &= ~(FILE_ALIGN - 1);
6394                 virtual_offset += VIRT_ALIGN - 1;
6395                 virtual_offset &= ~(VIRT_ALIGN - 1);
6396
6397                 assembly->sections [i].offset = file_offset;
6398                 assembly->sections [i].rva = virtual_offset;
6399
6400                 file_offset += assembly->sections [i].size;
6401                 virtual_offset += assembly->sections [i].size;
6402                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6403         }
6404
6405         file_offset += FILE_ALIGN - 1;
6406         file_offset &= ~(FILE_ALIGN - 1);
6407
6408         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6409
6410         /* back-patch info */
6411         msdos = (MonoMSDOSHeader*)pefile->data;
6412         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6413
6414         header = (MonoDotNetHeader*)(pefile->data + header_start);
6415         header->pesig [0] = 'P';
6416         header->pesig [1] = 'E';
6417         
6418         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6419         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6420         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6421         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6422         if (assemblyb->pekind == 1) {
6423                 /* it's a dll */
6424                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6425         } else {
6426                 /* it's an exe */
6427                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6428         }
6429
6430         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6431
6432         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6433         header->pe.pe_major = 6;
6434         header->pe.pe_minor = 0;
6435         size = assembly->sections [MONO_SECTION_TEXT].size;
6436         size += FILE_ALIGN - 1;
6437         size &= ~(FILE_ALIGN - 1);
6438         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6439         size = assembly->sections [MONO_SECTION_RSRC].size;
6440         size += FILE_ALIGN - 1;
6441         size &= ~(FILE_ALIGN - 1);
6442         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6443         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6444         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6445         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6446         /* pe_rva_entry_point always at the beginning of the text section */
6447         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6448
6449         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6450         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6451         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6452         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6453         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6454         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6455         size = section_start;
6456         size += FILE_ALIGN - 1;
6457         size &= ~(FILE_ALIGN - 1);
6458         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6459         size = image_size;
6460         size += VIRT_ALIGN - 1;
6461         size &= ~(VIRT_ALIGN - 1);
6462         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6463
6464         /*
6465         // Translate the PEFileKind value to the value expected by the Windows loader
6466         */
6467         {
6468                 short kind;
6469
6470                 /*
6471                 // PEFileKinds.Dll == 1
6472                 // PEFileKinds.ConsoleApplication == 2
6473                 // PEFileKinds.WindowApplication == 3
6474                 //
6475                 // need to get:
6476                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6477                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6478                 */
6479                 if (assemblyb->pekind == 3)
6480                         kind = 2;
6481                 else
6482                         kind = 3;
6483                 
6484                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6485         }    
6486         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6487         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6488         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6489         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6490         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6491         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6492
6493         /* fill data directory entries */
6494
6495         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6496         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6497
6498         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6499         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6500
6501         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6502         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6503         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6504         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6505         /* patch entrypoint name */
6506         if (assemblyb->pekind == 1)
6507                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6508         else
6509                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6510         /* patch imported function RVA name */
6511         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6512         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6513
6514         /* the import table */
6515         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6516         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6517         /* patch imported dll RVA name and other entries in the dir */
6518         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6519         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6520         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6521         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6522         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6523         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6524
6525         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6526         value = (assembly->text_rva + assembly->imp_names_offset);
6527         *p++ = (value) & 0xff;
6528         *p++ = (value >> 8) & (0xff);
6529         *p++ = (value >> 16) & (0xff);
6530         *p++ = (value >> 24) & (0xff);
6531
6532         /* the CLI header info */
6533         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6534         cli_header->ch_size = GUINT32_FROM_LE (72);
6535         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6536         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6537         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6538         if (assemblyb->entry_point) {
6539                 guint32 table_idx = 0;
6540                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6541                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6542                         table_idx = methodb->table_idx;
6543                 } else {
6544                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6545                 }
6546                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6547         } else {
6548                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6549         }
6550         /* The embedded managed resources */
6551         text_offset = assembly->text_rva + assembly->code.index;
6552         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6553         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6554         text_offset += assembly->resources.index;
6555         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6556         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6557         text_offset += assembly->meta_size;
6558         if (assembly->strong_name_size) {
6559                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6560                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6561                 text_offset += assembly->strong_name_size;
6562         }
6563
6564         /* write the section tables and section content */
6565         section = (MonoSectionTable*)(pefile->data + section_start);
6566         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6567                 static const char section_names [][7] = {
6568                         ".text", ".rsrc", ".reloc"
6569                 };
6570                 if (!assembly->sections [i].size)
6571                         continue;
6572                 strcpy (section->st_name, section_names [i]);
6573                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6574                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6575                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6576                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6577                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6578                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6579                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6580                 section ++;
6581         }
6582         
6583         checked_write_file (file, pefile->data, pefile->index);
6584         
6585         mono_dynamic_stream_reset (pefile);
6586         
6587         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6588                 if (!assembly->sections [i].size)
6589                         continue;
6590                 
6591                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6592                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6593                 
6594                 switch (i) {
6595                 case MONO_SECTION_TEXT:
6596                         /* patch entry point */
6597                         p = (guchar*)(assembly->code.data + 2);
6598                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6599                         *p++ = (value) & 0xff;
6600                         *p++ = (value >> 8) & 0xff;
6601                         *p++ = (value >> 16) & 0xff;
6602                         *p++ = (value >> 24) & 0xff;
6603                 
6604                         checked_write_file (file, assembly->code.data, assembly->code.index);
6605                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6606                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6607                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6608                                 
6609
6610                         g_free (assembly->image.raw_metadata);
6611                         break;
6612                 case MONO_SECTION_RELOC: {
6613                         struct {
6614                                 guint32 page_rva;
6615                                 guint32 block_size;
6616                                 guint16 type_and_offset;
6617                                 guint16 term;
6618                         } reloc;
6619                         
6620                         g_assert (sizeof (reloc) == 12);
6621                         
6622                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6623                         reloc.block_size = GUINT32_FROM_LE (12);
6624                         
6625                         /* 
6626                          * the entrypoint is always at the start of the text section 
6627                          * 3 is IMAGE_REL_BASED_HIGHLOW
6628                          * 2 is patch_size_rva - text_rva
6629                          */
6630                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6631                         reloc.term = 0;
6632                         
6633                         checked_write_file (file, &reloc, sizeof (reloc));
6634                         
6635                         break;
6636                 }
6637                 case MONO_SECTION_RSRC:
6638                         if (assembly->win32_res) {
6639
6640                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6641                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6642                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6643                         }
6644                         break;
6645                 default:
6646                         g_assert_not_reached ();
6647                 }
6648         }
6649         
6650         /* check that the file is properly padded */
6651         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6652                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6653         if (! SetEndOfFile (file))
6654                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6655         
6656         mono_dynamic_stream_reset (&assembly->code);
6657         mono_dynamic_stream_reset (&assembly->us);
6658         mono_dynamic_stream_reset (&assembly->blob);
6659         mono_dynamic_stream_reset (&assembly->guid);
6660         mono_dynamic_stream_reset (&assembly->sheap);
6661
6662         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6663         g_hash_table_destroy (assembly->blob_cache);
6664         assembly->blob_cache = NULL;
6665
6666         return TRUE;
6667 }
6668
6669 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6670
6671 gboolean
6672 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6673 {
6674         g_assert_not_reached ();
6675 }
6676
6677 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6678
6679 #ifndef DISABLE_REFLECTION_EMIT
6680
6681 MonoReflectionModule *
6682 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6683 {
6684         char *name;
6685         MonoImage *image;
6686         MonoImageOpenStatus status;
6687         MonoDynamicAssembly *assembly;
6688         guint32 module_count;
6689         MonoImage **new_modules;
6690         gboolean *new_modules_loaded;
6691         
6692         mono_error_init (error);
6693         
6694         name = mono_string_to_utf8 (fileName);
6695
6696         image = mono_image_open (name, &status);
6697         if (!image) {
6698                 if (status == MONO_IMAGE_ERROR_ERRNO)
6699                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6700                 else
6701                         mono_error_set_bad_image_name (error, name, NULL);
6702                 g_free (name);
6703                 return NULL;
6704         }
6705
6706         g_free (name);
6707
6708         assembly = ab->dynamic_assembly;
6709         image->assembly = (MonoAssembly*)assembly;
6710
6711         module_count = image->assembly->image->module_count;
6712         new_modules = g_new0 (MonoImage *, module_count + 1);
6713         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6714
6715         if (image->assembly->image->modules)
6716                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6717         if (image->assembly->image->modules_loaded)
6718                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6719         new_modules [module_count] = image;
6720         new_modules_loaded [module_count] = TRUE;
6721         mono_image_addref (image);
6722
6723         g_free (image->assembly->image->modules);
6724         image->assembly->image->modules = new_modules;
6725         image->assembly->image->modules_loaded = new_modules_loaded;
6726         image->assembly->image->module_count ++;
6727
6728         mono_assembly_load_references (image, &status);
6729         if (status) {
6730                 mono_image_close (image);
6731                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6732                 return NULL;
6733         }
6734
6735         return mono_module_get_object_checked (mono_domain_get (), image, error);
6736 }
6737
6738 #endif /* DISABLE_REFLECTION_EMIT */
6739
6740 /*
6741  * We need to return always the same object for MethodInfo, FieldInfo etc..
6742  * but we need to consider the reflected type.
6743  * type uses a different hash, since it uses custom hash/equal functions.
6744  */
6745
6746 typedef struct {
6747         gpointer item;
6748         MonoClass *refclass;
6749 } ReflectedEntry;
6750
6751 static gboolean
6752 reflected_equal (gconstpointer a, gconstpointer b) {
6753         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6754         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6755
6756         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6757 }
6758
6759 static guint
6760 reflected_hash (gconstpointer a) {
6761         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6762         return mono_aligned_addr_hash (ea->item);
6763 }
6764
6765 #define CHECK_OBJECT(t,p,k)     \
6766         do {    \
6767                 t _obj; \
6768                 ReflectedEntry e;       \
6769                 e.item = (p);   \
6770                 e.refclass = (k);       \
6771                 mono_domain_lock (domain);      \
6772                 if (!domain->refobject_hash)    \
6773                         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");  \
6774                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6775                         mono_domain_unlock (domain);    \
6776                         return _obj;    \
6777                 }       \
6778         mono_domain_unlock (domain); \
6779         } while (0)
6780
6781 #ifdef HAVE_BOEHM_GC
6782 /* ReflectedEntry doesn't need to be GC tracked */
6783 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6784 #define FREE_REFENTRY(entry) g_free ((entry))
6785 #define REFENTRY_REQUIRES_CLEANUP
6786 #else
6787 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6788 /* FIXME: */
6789 #define FREE_REFENTRY(entry)
6790 #endif
6791
6792 #define CACHE_OBJECT(t,p,o,k)   \
6793         do {    \
6794                 t _obj; \
6795         ReflectedEntry pe; \
6796         pe.item = (p); \
6797         pe.refclass = (k); \
6798         mono_domain_lock (domain); \
6799                 if (!domain->refobject_hash)    \
6800                         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");  \
6801         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6802         if (!_obj) { \
6803                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6804                     e->item = (p);      \
6805                     e->refclass = (k);  \
6806                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6807             _obj = o; \
6808         } \
6809                 mono_domain_unlock (domain);    \
6810         return _obj; \
6811         } while (0)
6812
6813 static void
6814 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6815 {
6816         mono_domain_lock (domain);
6817         if (domain->refobject_hash) {
6818         ReflectedEntry pe;
6819                 gpointer orig_pe, orig_value;
6820
6821                 pe.item = o;
6822                 pe.refclass = klass;
6823                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6824                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6825                         FREE_REFENTRY (orig_pe);
6826                 }
6827         }
6828         mono_domain_unlock (domain);
6829 }
6830
6831 #ifdef REFENTRY_REQUIRES_CLEANUP
6832 static void
6833 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6834 {
6835         FREE_REFENTRY (key);
6836 }
6837 #endif
6838
6839 void
6840 mono_reflection_cleanup_domain (MonoDomain *domain)
6841 {
6842         if (domain->refobject_hash) {
6843 /*let's avoid scanning the whole hashtable if not needed*/
6844 #ifdef REFENTRY_REQUIRES_CLEANUP
6845                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6846 #endif
6847                 mono_g_hash_table_destroy (domain->refobject_hash);
6848                 domain->refobject_hash = NULL;
6849         }
6850 }
6851
6852 #ifndef DISABLE_REFLECTION_EMIT
6853 static gpointer
6854 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6855 {
6856         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6857 }
6858
6859 static gpointer
6860 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6861 {
6862         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6863 }
6864
6865 static gboolean
6866 image_module_basic_init (MonoReflectionModuleBuilder *moduleb, MonoError *error)
6867 {
6868         MonoDynamicImage *image = moduleb->dynamic_image;
6869         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6870         mono_error_init (error);
6871         if (!image) {
6872                 int module_count;
6873                 MonoImage **new_modules;
6874                 MonoImage *ass;
6875                 char *name, *fqname;
6876                 /*
6877                  * FIXME: we already created an image in mono_image_basic_init (), but
6878                  * we don't know which module it belongs to, since that is only 
6879                  * determined at assembly save time.
6880                  */
6881                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6882                 name = mono_string_to_utf8 (ab->name);
6883                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, error);
6884                 if (!is_ok (error)) {
6885                         g_free (name);
6886                         return FALSE;
6887                 }
6888                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6889
6890                 moduleb->module.image = &image->image;
6891                 moduleb->dynamic_image = image;
6892                 register_module (mono_object_domain (moduleb), moduleb, image);
6893
6894                 /* register the module with the assembly */
6895                 ass = ab->dynamic_assembly->assembly.image;
6896                 module_count = ass->module_count;
6897                 new_modules = g_new0 (MonoImage *, module_count + 1);
6898
6899                 if (ass->modules)
6900                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6901                 new_modules [module_count] = &image->image;
6902                 mono_image_addref (&image->image);
6903
6904                 g_free (ass->modules);
6905                 ass->modules = new_modules;
6906                 ass->module_count ++;
6907         }
6908         return TRUE;
6909 }
6910
6911 void
6912 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6913 {
6914         MonoError error;
6915         (void) image_module_basic_init (moduleb, &error);
6916         mono_error_set_pending_exception (&error);
6917 }
6918
6919 void
6920 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6921 {
6922         MonoDynamicImage *image = moduleb->dynamic_image;
6923
6924         g_assert (type->type);
6925         image->wrappers_type = mono_class_from_mono_type (type->type);
6926 }
6927
6928 #endif
6929
6930 /*
6931  * mono_assembly_get_object:
6932  * @domain: an app domain
6933  * @assembly: an assembly
6934  *
6935  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6936  */
6937 MonoReflectionAssembly*
6938 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6939 {
6940         MonoError error;
6941         MonoReflectionAssembly *result;
6942         result = mono_assembly_get_object_checked (domain, assembly, &error);
6943         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6944         return result;
6945 }
6946 /*
6947  * mono_assembly_get_object_checked:
6948  * @domain: an app domain
6949  * @assembly: an assembly
6950  *
6951  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6952  */
6953 MonoReflectionAssembly*
6954 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6955 {
6956         MonoReflectionAssembly *res;
6957         
6958         mono_error_init (error);
6959
6960         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6961         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6962         if (!res)
6963                 return NULL;
6964         res->assembly = assembly;
6965
6966         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6967 }
6968
6969
6970
6971 MonoReflectionModule*   
6972 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6973 {
6974         MonoError error;
6975         MonoReflectionModule *result;
6976         result = mono_module_get_object_checked (domain, image, &error);
6977         mono_error_cleanup (&error);
6978         return result;
6979 }
6980
6981 MonoReflectionModule*
6982 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6983 {
6984         MonoReflectionModule *res;
6985         char* basename;
6986         
6987         mono_error_init (error);
6988         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6989         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6990         if (!res)
6991                 return NULL;
6992
6993         res->image = image;
6994         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6995         if (!assm_obj)
6996                 return NULL;
6997         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6998
6999         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
7000         basename = g_path_get_basename (image->name);
7001         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
7002         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
7003         
7004         g_free (basename);
7005
7006         if (image->assembly->image == image) {
7007                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
7008         } else {
7009                 int i;
7010                 res->token = 0;
7011                 if (image->assembly->image->modules) {
7012                         for (i = 0; i < image->assembly->image->module_count; i++) {
7013                                 if (image->assembly->image->modules [i] == image)
7014                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
7015                         }
7016                         g_assert (res->token);
7017                 }
7018         }
7019
7020         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7021 }
7022
7023 MonoReflectionModule*
7024 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7025 {
7026         MonoError error;
7027         MonoReflectionModule *result;
7028         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7029         mono_error_cleanup (&error);
7030         return result;
7031 }
7032
7033 MonoReflectionModule*
7034 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7035 {
7036         MonoReflectionModule *res;
7037         MonoTableInfo *table;
7038         guint32 cols [MONO_FILE_SIZE];
7039         const char *name;
7040         guint32 i, name_idx;
7041         const char *val;
7042         
7043         mono_error_init (error);
7044
7045         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7046         if (!res)
7047                 return NULL;
7048
7049         table = &image->tables [MONO_TABLE_FILE];
7050         g_assert (table_index < table->rows);
7051         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7052
7053         res->image = NULL;
7054         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7055         if (!assm_obj)
7056                 return NULL;
7057         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7058         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7059
7060         /* Check whenever the row has a corresponding row in the moduleref table */
7061         table = &image->tables [MONO_TABLE_MODULEREF];
7062         for (i = 0; i < table->rows; ++i) {
7063                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7064                 val = mono_metadata_string_heap (image, name_idx);
7065                 if (strcmp (val, name) == 0)
7066                         res->image = image->modules [i];
7067         }
7068
7069         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7070         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7071         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7072         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7073         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7074
7075         return res;
7076 }
7077
7078 static gboolean
7079 verify_safe_for_managed_space (MonoType *type)
7080 {
7081         switch (type->type) {
7082 #ifdef DEBUG_HARDER
7083         case MONO_TYPE_ARRAY:
7084                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7085         case MONO_TYPE_PTR:
7086                 return verify_safe_for_managed_space (type->data.type);
7087         case MONO_TYPE_SZARRAY:
7088                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7089         case MONO_TYPE_GENERICINST: {
7090                 MonoGenericInst *inst = type->data.generic_class->inst;
7091                 int i;
7092                 if (!inst->is_open)
7093                         break;
7094                 for (i = 0; i < inst->type_argc; ++i)
7095                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7096                                 return FALSE;
7097                 return TRUE;
7098         }
7099 #endif
7100         case MONO_TYPE_VAR:
7101         case MONO_TYPE_MVAR:
7102                 return TRUE;
7103         default:
7104                 return TRUE;
7105         }
7106 }
7107
7108 static MonoType*
7109 mono_type_normalize (MonoType *type)
7110 {
7111         int i;
7112         MonoGenericClass *gclass;
7113         MonoGenericInst *ginst;
7114         MonoClass *gtd;
7115         MonoGenericContainer *gcontainer;
7116         MonoType **argv = NULL;
7117         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7118
7119         if (type->type != MONO_TYPE_GENERICINST)
7120                 return type;
7121
7122         gclass = type->data.generic_class;
7123         ginst = gclass->context.class_inst;
7124         if (!ginst->is_open)
7125                 return type;
7126
7127         gtd = gclass->container_class;
7128         gcontainer = gtd->generic_container;
7129         argv = g_newa (MonoType*, ginst->type_argc);
7130
7131         for (i = 0; i < ginst->type_argc; ++i) {
7132                 MonoType *t = ginst->type_argv [i], *norm;
7133                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7134                         is_denorm_gtd = FALSE;
7135                 norm = mono_type_normalize (t);
7136                 argv [i] = norm;
7137                 if (norm != t)
7138                         requires_rebind = TRUE;
7139         }
7140
7141         if (is_denorm_gtd)
7142                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7143
7144         if (requires_rebind) {
7145                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7146                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7147         }
7148
7149         return type;
7150 }
7151 /*
7152  * mono_type_get_object:
7153  * @domain: an app domain
7154  * @type: a type
7155  *
7156  * Return an System.MonoType object representing the type @type.
7157  */
7158 MonoReflectionType*
7159 mono_type_get_object (MonoDomain *domain, MonoType *type)
7160 {
7161         MonoError error;
7162         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7163         mono_error_cleanup (&error);
7164
7165         return ret;
7166 }
7167
7168 MonoReflectionType*
7169 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7170 {
7171         MonoType *norm_type;
7172         MonoReflectionType *res;
7173         MonoClass *klass;
7174
7175         mono_error_init (error);
7176
7177         klass = mono_class_from_mono_type (type);
7178
7179         /*we must avoid using @type as it might have come
7180          * from a mono_metadata_type_dup and the caller
7181          * expects that is can be freed.
7182          * Using the right type from 
7183          */
7184         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7185
7186         /* void is very common */
7187         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7188                 return (MonoReflectionType*)domain->typeof_void;
7189
7190         /*
7191          * If the vtable of the given class was already created, we can use
7192          * the MonoType from there and avoid all locking and hash table lookups.
7193          * 
7194          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7195          * that the resulting object is different.   
7196          */
7197         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7198                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7199                 if (vtable && vtable->type)
7200                         return (MonoReflectionType *)vtable->type;
7201         }
7202
7203         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7204         mono_domain_lock (domain);
7205         if (!domain->type_hash)
7206                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7207                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7208         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7209                 mono_domain_unlock (domain);
7210                 mono_loader_unlock ();
7211                 return res;
7212         }
7213
7214         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7215          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7216          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7217          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7218          * artifact of how generics are encoded and should be transparent to managed code so we
7219          * need to weed out this diference when retrieving managed System.Type objects.
7220          */
7221         norm_type = mono_type_normalize (type);
7222         if (norm_type != type) {
7223                 res = mono_type_get_object_checked (domain, norm_type, error);
7224                 if (!mono_error_ok (error))
7225                         return NULL;
7226                 mono_g_hash_table_insert (domain->type_hash, type, res);
7227                 mono_domain_unlock (domain);
7228                 mono_loader_unlock ();
7229                 return res;
7230         }
7231
7232         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7233         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7234                 g_assert (0);
7235
7236         if (!verify_safe_for_managed_space (type)) {
7237                 mono_domain_unlock (domain);
7238                 mono_loader_unlock ();
7239                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7240                 return NULL;
7241         }
7242
7243         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7244                 gboolean is_type_done = TRUE;
7245                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7246                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7247                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7248                 */
7249                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7250                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7251
7252                         if (gparam->owner && gparam->owner->is_method) {
7253                                 MonoMethod *method = gparam->owner->owner.method;
7254                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7255                                         is_type_done = FALSE;
7256                         } else if (gparam->owner && !gparam->owner->is_method) {
7257                                 MonoClass *klass = gparam->owner->owner.klass;
7258                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7259                                         is_type_done = FALSE;
7260                         }
7261                 } 
7262
7263                 /* g_assert_not_reached (); */
7264                 /* should this be considered an error condition? */
7265                 if (is_type_done && !type->byref) {
7266                         mono_domain_unlock (domain);
7267                         mono_loader_unlock ();
7268                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7269                 }
7270         }
7271         /* This is stored in vtables/JITted code so it has to be pinned */
7272         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7273         if (!mono_error_ok (error))
7274                 return NULL;
7275
7276         res->type = type;
7277         mono_g_hash_table_insert (domain->type_hash, type, res);
7278
7279         if (type->type == MONO_TYPE_VOID)
7280                 domain->typeof_void = (MonoObject*)res;
7281
7282         mono_domain_unlock (domain);
7283         mono_loader_unlock ();
7284         return res;
7285 }
7286
7287 /*
7288  * mono_method_get_object:
7289  * @domain: an app domain
7290  * @method: a method
7291  * @refclass: the reflected type (can be NULL)
7292  *
7293  * Return an System.Reflection.MonoMethod object representing the method @method.
7294  */
7295 MonoReflectionMethod*
7296 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7297 {
7298         MonoError error;
7299         MonoReflectionMethod *ret = NULL;
7300         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7301         mono_error_cleanup (&error);
7302         return ret;
7303 }
7304
7305 /*
7306  * mono_method_get_object_checked:
7307  * @domain: an app domain
7308  * @method: a method
7309  * @refclass: the reflected type (can be NULL)
7310  * @error: set on error.
7311  *
7312  * Return an System.Reflection.MonoMethod object representing the method @method.
7313  * Returns NULL and sets @error on error.
7314  */
7315 MonoReflectionMethod*
7316 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7317 {
7318         /*
7319          * We use the same C representation for methods and constructors, but the type 
7320          * name in C# is different.
7321          */
7322         MonoReflectionType *rt;
7323         MonoClass *klass;
7324         MonoReflectionMethod *ret;
7325
7326         mono_error_init (error);
7327
7328         if (method->is_inflated) {
7329                 MonoReflectionGenericMethod *gret;
7330
7331                 if (!refclass)
7332                         refclass = method->klass;
7333                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7334                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7335                         klass = mono_class_get_mono_generic_cmethod_class ();
7336                 } else {
7337                         klass = mono_class_get_mono_generic_method_class ();
7338                 }
7339                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7340                 if (!mono_error_ok (error))
7341                         goto leave;
7342                 gret->method.method = method;
7343
7344                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7345
7346                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7347                 if (!mono_error_ok (error))
7348                     goto leave;
7349
7350                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7351
7352                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7353         }
7354
7355         if (!refclass)
7356                 refclass = method->klass;
7357
7358         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7359         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7360                 klass = mono_class_get_mono_cmethod_class ();
7361         }
7362         else {
7363                 klass = mono_class_get_mono_method_class ();
7364         }
7365         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7366         if (!mono_error_ok (error))
7367                 goto leave;
7368         ret->method = method;
7369
7370         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7371         if (!mono_error_ok (error))
7372                 goto leave;
7373
7374         MONO_OBJECT_SETREF (ret, reftype, rt);
7375
7376         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7377
7378 leave:
7379         g_assert (!mono_error_ok (error));
7380         return NULL;
7381 }
7382
7383 /*
7384  * mono_method_clear_object:
7385  *
7386  *   Clear the cached reflection objects for the dynamic method METHOD.
7387  */
7388 void
7389 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7390 {
7391         MonoClass *klass;
7392         g_assert (method_is_dynamic (method));
7393
7394         klass = method->klass;
7395         while (klass) {
7396                 clear_cached_object (domain, method, klass);
7397                 klass = klass->parent;
7398         }
7399         /* Added by mono_param_get_objects () */
7400         clear_cached_object (domain, &(method->signature), NULL);
7401         klass = method->klass;
7402         while (klass) {
7403                 clear_cached_object (domain, &(method->signature), klass);
7404                 klass = klass->parent;
7405         }
7406 }
7407
7408 /*
7409  * mono_field_get_object:
7410  * @domain: an app domain
7411  * @klass: a type
7412  * @field: a field
7413  *
7414  * Return an System.Reflection.MonoField object representing the field @field
7415  * in class @klass.
7416  */
7417 MonoReflectionField*
7418 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7419 {
7420         MonoError error;
7421         MonoReflectionField *result;
7422         result = mono_field_get_object_checked (domain, klass, field, &error);
7423         mono_error_cleanup (&error);
7424         return result;
7425 }
7426
7427 /*
7428  * mono_field_get_object_checked:
7429  * @domain: an app domain
7430  * @klass: a type
7431  * @field: a field
7432  * @error: set on error
7433  *
7434  * Return an System.Reflection.MonoField object representing the field @field
7435  * in class @klass. On error, returns NULL and sets @error.
7436  */
7437 MonoReflectionField*
7438 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7439 {
7440         MonoReflectionType *rt;
7441         MonoReflectionField *res;
7442
7443         mono_error_init (error);
7444
7445         CHECK_OBJECT (MonoReflectionField *, field, klass);
7446         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7447         if (!res)
7448                 return NULL;
7449         res->klass = klass;
7450         res->field = field;
7451         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7452
7453         if (is_field_on_inst (field)) {
7454                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7455
7456                 rt = mono_type_get_object_checked (domain, field->type, error);
7457                 if (!mono_error_ok (error))
7458                         return NULL;
7459
7460                 MONO_OBJECT_SETREF (res, type, rt);
7461         } else {
7462                 if (field->type) {
7463                         rt = mono_type_get_object_checked (domain, field->type, error);
7464                         if (!mono_error_ok (error))
7465                                 return NULL;
7466
7467                         MONO_OBJECT_SETREF (res, type, rt);
7468                 }
7469                 res->attrs = mono_field_get_flags (field);
7470         }
7471         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7472 }
7473
7474 /*
7475  * mono_property_get_object:
7476  * @domain: an app domain
7477  * @klass: a type
7478  * @property: a property
7479  *
7480  * Return an System.Reflection.MonoProperty object representing the property @property
7481  * in class @klass.
7482  */
7483 MonoReflectionProperty*
7484 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7485 {
7486         MonoError error;
7487         MonoReflectionProperty *result;
7488         result = mono_property_get_object_checked (domain, klass, property, &error);
7489         mono_error_cleanup (&error);
7490         return result;
7491 }
7492
7493 /**
7494  * mono_property_get_object:
7495  * @domain: an app domain
7496  * @klass: a type
7497  * @property: a property
7498  * @error: set on error
7499  *
7500  * Return an System.Reflection.MonoProperty object representing the property @property
7501  * in class @klass.  On error returns NULL and sets @error.
7502  */
7503 MonoReflectionProperty*
7504 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7505 {
7506         MonoReflectionProperty *res;
7507
7508         mono_error_init (error);
7509
7510         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7511         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7512         if (!res)
7513                 return NULL;
7514         res->klass = klass;
7515         res->property = property;
7516         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7517 }
7518
7519 /*
7520  * mono_event_get_object:
7521  * @domain: an app domain
7522  * @klass: a type
7523  * @event: a event
7524  *
7525  * Return an System.Reflection.MonoEvent object representing the event @event
7526  * in class @klass.
7527  */
7528 MonoReflectionEvent*
7529 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7530 {
7531         MonoError error;
7532         MonoReflectionEvent *result;
7533         result = mono_event_get_object_checked (domain, klass, event, &error);
7534         mono_error_cleanup (&error);
7535         return result;
7536 }
7537
7538 /**
7539  * mono_event_get_object_checked:
7540  * @domain: an app domain
7541  * @klass: a type
7542  * @event: a event
7543  * @error: set on error
7544  *
7545  * Return an System.Reflection.MonoEvent object representing the event @event
7546  * in class @klass. On failure sets @error and returns NULL
7547  */
7548 MonoReflectionEvent*
7549 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7550 {
7551         MonoReflectionEvent *res;
7552         MonoReflectionMonoEvent *mono_event;
7553
7554         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7555         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7556         if (!mono_event)
7557                 return NULL;
7558         mono_event->klass = klass;
7559         mono_event->event = event;
7560         res = (MonoReflectionEvent*)mono_event;
7561         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7562 }
7563
7564 /**
7565  * mono_get_reflection_missing_object:
7566  * @domain: Domain where the object lives
7567  *
7568  * Returns the System.Reflection.Missing.Value singleton object
7569  * (of type System.Reflection.Missing).
7570  *
7571  * Used as the value for ParameterInfo.DefaultValue when Optional
7572  * is present
7573  */
7574 static MonoObject *
7575 mono_get_reflection_missing_object (MonoDomain *domain)
7576 {
7577         MonoError error;
7578         MonoObject *obj;
7579         static MonoClassField *missing_value_field = NULL;
7580         
7581         if (!missing_value_field) {
7582                 MonoClass *missing_klass;
7583                 missing_klass = mono_class_get_missing_class ();
7584                 mono_class_init (missing_klass);
7585                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7586                 g_assert (missing_value_field);
7587         }
7588         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7589         mono_error_assert_ok (&error);
7590         return obj;
7591 }
7592
7593 static MonoObject*
7594 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7595 {
7596         if (!*dbnull)
7597                 *dbnull = mono_get_dbnull_object (domain);
7598         return *dbnull;
7599 }
7600
7601 static MonoObject*
7602 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7603 {
7604         if (!*reflection_missing)
7605                 *reflection_missing = mono_get_reflection_missing_object (domain);
7606         return *reflection_missing;
7607 }
7608
7609 /*
7610  * mono_param_get_objects:
7611  * @domain: an app domain
7612  * @method: a method
7613  *
7614  * Return an System.Reflection.ParameterInfo array object representing the parameters
7615  * in the method @method.
7616  */
7617 MonoArray*
7618 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7619 {
7620         static MonoClass *System_Reflection_ParameterInfo;
7621         static MonoClass *System_Reflection_ParameterInfo_array;
7622         MonoArray *res = NULL;
7623         MonoReflectionMethod *member = NULL;
7624         MonoReflectionParameter *param = NULL;
7625         char **names = NULL, **blobs = NULL;
7626         guint32 *types = NULL;
7627         MonoType *type = NULL;
7628         MonoObject *dbnull = NULL;
7629         MonoObject *missing = NULL;
7630         MonoMarshalSpec **mspecs = NULL;
7631         MonoMethodSignature *sig = NULL;
7632         MonoVTable *pinfo_vtable;
7633         MonoReflectionType *rt;
7634         int i;
7635
7636         mono_error_init (error);
7637         
7638         if (!System_Reflection_ParameterInfo_array) {
7639                 MonoClass *klass;
7640
7641                 klass = mono_class_get_mono_parameter_info_class ();
7642
7643                 mono_memory_barrier ();
7644                 System_Reflection_ParameterInfo = klass; 
7645
7646         
7647                 klass = mono_array_class_get (klass, 1);
7648                 mono_memory_barrier ();
7649                 System_Reflection_ParameterInfo_array = klass;
7650         }
7651
7652         sig = mono_method_signature_checked (method, error);
7653         if (!mono_error_ok (error))
7654                 goto leave;
7655
7656         if (!sig->param_count) {
7657                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7658                 if (!res)
7659                         goto leave;
7660
7661                 return res;
7662         }
7663
7664         /* Note: the cache is based on the address of the signature into the method
7665          * since we already cache MethodInfos with the method as keys.
7666          */
7667         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7668
7669         member = mono_method_get_object_checked (domain, method, refclass, error);
7670         if (!member)
7671                 goto leave;
7672         names = g_new (char *, sig->param_count);
7673         mono_method_get_param_names (method, (const char **) names);
7674
7675         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7676         mono_method_get_marshal_info (method, mspecs);
7677
7678         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7679         if (!res)
7680                 goto leave;
7681
7682         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7683         for (i = 0; i < sig->param_count; ++i) {
7684                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7685                 if (!param)
7686                         goto leave;
7687
7688                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7689                 if (!rt)
7690                         goto leave;
7691
7692                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7693
7694                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7695
7696                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7697
7698                 param->PositionImpl = i;
7699                 param->AttrsImpl = sig->params [i]->attrs;
7700
7701                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7702                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7703                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7704                         else
7705                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7706                 } else {
7707
7708                         if (!blobs) {
7709                                 blobs = g_new0 (char *, sig->param_count);
7710                                 types = g_new0 (guint32, sig->param_count);
7711                                 get_default_param_value_blobs (method, blobs, types); 
7712                         }
7713
7714                         /* Build MonoType for the type from the Constant Table */
7715                         if (!type)
7716                                 type = g_new0 (MonoType, 1);
7717                         type->type = (MonoTypeEnum)types [i];
7718                         type->data.klass = NULL;
7719                         if (types [i] == MONO_TYPE_CLASS)
7720                                 type->data.klass = mono_defaults.object_class;
7721                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7722                                 /* For enums, types [i] contains the base type */
7723
7724                                         type->type = MONO_TYPE_VALUETYPE;
7725                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7726                         } else
7727                                 type->data.klass = mono_class_from_mono_type (type);
7728
7729                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7730                         if (!is_ok (error))
7731                                 goto leave;
7732                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7733
7734                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7735                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7736                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7737                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7738                                 else
7739                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7740                         }
7741                         
7742                 }
7743
7744                 if (mspecs [i + 1]) {
7745                         MonoReflectionMarshalAsAttribute* mobj;
7746                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7747                         if (!mobj)
7748                                 goto leave;
7749                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7750                 }
7751                 
7752                 mono_array_setref (res, i, param);
7753         }
7754
7755 leave:
7756         g_free (names);
7757         g_free (blobs);
7758         g_free (types);
7759         g_free (type);
7760
7761         if (sig) {
7762                 for (i = sig->param_count; i >= 0; i--) {
7763                         if (mspecs [i])
7764                                 mono_metadata_free_marshal_spec (mspecs [i]);
7765                 }
7766         }
7767         g_free (mspecs);
7768
7769         if (!is_ok (error))
7770                 return NULL;
7771         
7772         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7773 }
7774
7775 MonoArray*
7776 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7777 {
7778         MonoError error;
7779         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7780         mono_error_assert_ok (&error);
7781         return result;
7782 }
7783
7784 /*
7785  * mono_method_body_get_object:
7786  * @domain: an app domain
7787  * @method: a method
7788  *
7789  * Return an System.Reflection.MethodBody object representing the method @method.
7790  */
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7793 {
7794         MonoError error;
7795         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7796         mono_error_cleanup (&error);
7797         return result;
7798 }
7799
7800 /**
7801  * mono_method_body_get_object_checked:
7802  * @domain: an app domain
7803  * @method: a method
7804  * @error: set on error
7805  *
7806  * Return an System.Reflection.MethodBody object representing the
7807  * method @method.  On failure, returns NULL and sets @error.
7808  */
7809 MonoReflectionMethodBody*
7810 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7811 {
7812         MonoReflectionMethodBody *ret;
7813         MonoMethodHeader *header;
7814         MonoImage *image;
7815         MonoReflectionType *rt;
7816         guint32 method_rva, local_var_sig_token;
7817         char *ptr;
7818         unsigned char format, flags;
7819         int i;
7820
7821         mono_error_init (error);
7822
7823         /* for compatibility with .net */
7824         if (method_is_dynamic (method)) {
7825                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7826                 return NULL;
7827         }
7828
7829         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7830
7831         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7832                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7833             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7834                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7835             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7836                 return NULL;
7837
7838         image = method->klass->image;
7839         header = mono_method_get_header_checked (method, error);
7840         return_val_if_nok (error, NULL);
7841
7842         if (!image_is_dynamic (image)) {
7843                 /* Obtain local vars signature token */
7844                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7845                 ptr = mono_image_rva_map (image, method_rva);
7846                 flags = *(const unsigned char *) ptr;
7847                 format = flags & METHOD_HEADER_FORMAT_MASK;
7848                 switch (format){
7849                 case METHOD_HEADER_TINY_FORMAT:
7850                         local_var_sig_token = 0;
7851                         break;
7852                 case METHOD_HEADER_FAT_FORMAT:
7853                         ptr += 2;
7854                         ptr += 2;
7855                         ptr += 4;
7856                         local_var_sig_token = read32 (ptr);
7857                         break;
7858                 default:
7859                         g_assert_not_reached ();
7860                 }
7861         } else
7862                 local_var_sig_token = 0; //FIXME
7863
7864         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7865         if (!is_ok (error))
7866                 goto fail;
7867
7868         ret->init_locals = header->init_locals;
7869         ret->max_stack = header->max_stack;
7870         ret->local_var_sig_token = local_var_sig_token;
7871         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7872         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7873
7874         /* Locals */
7875         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7876         for (i = 0; i < header->num_locals; ++i) {
7877                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7878                 if (!is_ok (error))
7879                         goto fail;
7880
7881                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7882                 if (!is_ok (error))
7883                         goto fail;
7884
7885                 MONO_OBJECT_SETREF (info, local_type, rt);
7886
7887                 info->is_pinned = header->locals [i]->pinned;
7888                 info->local_index = i;
7889                 mono_array_setref (ret->locals, i, info);
7890         }
7891
7892         /* Exceptions */
7893         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7894         for (i = 0; i < header->num_clauses; ++i) {
7895                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7896                 if (!is_ok (error))
7897                         goto fail;
7898                 MonoExceptionClause *clause = &header->clauses [i];
7899
7900                 info->flags = clause->flags;
7901                 info->try_offset = clause->try_offset;
7902                 info->try_length = clause->try_len;
7903                 info->handler_offset = clause->handler_offset;
7904                 info->handler_length = clause->handler_len;
7905                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7906                         info->filter_offset = clause->data.filter_offset;
7907                 else if (clause->data.catch_class) {
7908                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7909                         if (!is_ok (error))
7910                                 goto fail;
7911
7912                         MONO_OBJECT_SETREF (info, catch_type, rt);
7913                 }
7914
7915                 mono_array_setref (ret->clauses, i, info);
7916         }
7917
7918         mono_metadata_free_mh (header);
7919         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7920         return ret;
7921
7922 fail:
7923         mono_metadata_free_mh (header);
7924         return NULL;
7925 }
7926
7927 /**
7928  * mono_get_dbnull_object:
7929  * @domain: Domain where the object lives
7930  *
7931  * Returns the System.DBNull.Value singleton object
7932  *
7933  * Used as the value for ParameterInfo.DefaultValue 
7934  */
7935 MonoObject *
7936 mono_get_dbnull_object (MonoDomain *domain)
7937 {
7938         MonoError error;
7939         MonoObject *obj;
7940         static MonoClassField *dbnull_value_field = NULL;
7941         
7942         if (!dbnull_value_field) {
7943                 MonoClass *dbnull_klass;
7944                 dbnull_klass = mono_class_get_dbnull_class ();
7945                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7946                 g_assert (dbnull_value_field);
7947         }
7948         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7949         mono_error_assert_ok (&error);
7950         return obj;
7951 }
7952
7953 static void
7954 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7955 {
7956         guint32 param_index, i, lastp, crow = 0;
7957         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7958         gint32 idx;
7959
7960         MonoClass *klass = method->klass;
7961         MonoImage *image = klass->image;
7962         MonoMethodSignature *methodsig = mono_method_signature (method);
7963
7964         MonoTableInfo *constt;
7965         MonoTableInfo *methodt;
7966         MonoTableInfo *paramt;
7967
7968         if (!methodsig->param_count)
7969                 return;
7970
7971         mono_class_init (klass);
7972
7973         if (image_is_dynamic (klass->image)) {
7974                 MonoReflectionMethodAux *aux;
7975                 if (method->is_inflated)
7976                         method = ((MonoMethodInflated*)method)->declaring;
7977                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7978                 if (aux && aux->param_defaults) {
7979                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7980                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7981                 }
7982                 return;
7983         }
7984
7985         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7986         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7987         constt = &image->tables [MONO_TABLE_CONSTANT];
7988
7989         idx = mono_method_get_index (method) - 1;
7990         g_assert (idx != -1);
7991
7992         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7993         if (idx + 1 < methodt->rows)
7994                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7995         else
7996                 lastp = paramt->rows + 1;
7997
7998         for (i = param_index; i < lastp; ++i) {
7999                 guint32 paramseq;
8000
8001                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
8002                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
8003
8004                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
8005                         continue;
8006
8007                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
8008                 if (!crow) {
8009                         continue;
8010                 }
8011         
8012                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
8013                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
8014                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
8015         }
8016
8017         return;
8018 }
8019
8020 MonoObject *
8021 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8022 {
8023         void *retval;
8024         MonoClass *klass;
8025         MonoObject *object;
8026         MonoType *basetype = type;
8027
8028         mono_error_init (error);
8029
8030         if (!blob)
8031                 return NULL;
8032         
8033         klass = mono_class_from_mono_type (type);
8034         if (klass->valuetype) {
8035                 object = mono_object_new_checked (domain, klass, error);
8036                 return_val_if_nok (error, NULL);
8037                 retval = ((gchar *) object + sizeof (MonoObject));
8038                 if (klass->enumtype)
8039                         basetype = mono_class_enum_basetype (klass);
8040         } else {
8041                 retval = &object;
8042         }
8043                         
8044         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
8045                 return object;
8046         else
8047                 return NULL;
8048 }
8049
8050 static int
8051 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8052         int found_sep;
8053         char *s;
8054         gboolean quoted = FALSE;
8055
8056         memset (assembly, 0, sizeof (MonoAssemblyName));
8057         assembly->culture = "";
8058         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8059
8060         if (*p == '"') {
8061                 quoted = TRUE;
8062                 p++;
8063         }
8064         assembly->name = p;
8065         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8066                 p++;
8067         if (quoted) {
8068                 if (*p != '"')
8069                         return 1;
8070                 *p = 0;
8071                 p++;
8072         }
8073         if (*p != ',')
8074                 return 1;
8075         *p = 0;
8076         /* Remove trailing whitespace */
8077         s = p - 1;
8078         while (*s && g_ascii_isspace (*s))
8079                 *s-- = 0;
8080         p ++;
8081         while (g_ascii_isspace (*p))
8082                 p++;
8083         while (*p) {
8084                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8085                         p += 8;
8086                         assembly->major = strtoul (p, &s, 10);
8087                         if (s == p || *s != '.')
8088                                 return 1;
8089                         p = ++s;
8090                         assembly->minor = strtoul (p, &s, 10);
8091                         if (s == p || *s != '.')
8092                                 return 1;
8093                         p = ++s;
8094                         assembly->build = strtoul (p, &s, 10);
8095                         if (s == p || *s != '.')
8096                                 return 1;
8097                         p = ++s;
8098                         assembly->revision = strtoul (p, &s, 10);
8099                         if (s == p)
8100                                 return 1;
8101                         p = s;
8102                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8103                         p += 8;
8104                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8105                                 assembly->culture = "";
8106                                 p += 7;
8107                         } else {
8108                                 assembly->culture = p;
8109                                 while (*p && *p != ',') {
8110                                         p++;
8111                                 }
8112                         }
8113                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8114                         p += 15;
8115                         if (strncmp (p, "null", 4) == 0) {
8116                                 p += 4;
8117                         } else {
8118                                 int len;
8119                                 gchar *start = p;
8120                                 while (*p && *p != ',') {
8121                                         p++;
8122                                 }
8123                                 len = (p - start + 1);
8124                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8125                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8126                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8127                         }
8128                 } else {
8129                         while (*p && *p != ',')
8130                                 p++;
8131                 }
8132                 found_sep = 0;
8133                 while (g_ascii_isspace (*p) || *p == ',') {
8134                         *p++ = 0;
8135                         found_sep = 1;
8136                         continue;
8137                 }
8138                 /* failed */
8139                 if (!found_sep)
8140                         return 1;
8141         }
8142
8143         return 0;
8144 }
8145
8146 /*
8147  * mono_reflection_parse_type:
8148  * @name: type name
8149  *
8150  * Parse a type name as accepted by the GetType () method and output the info
8151  * extracted in the info structure.
8152  * the name param will be mangled, so, make a copy before passing it to this function.
8153  * The fields in info will be valid until the memory pointed to by name is valid.
8154  *
8155  * See also mono_type_get_name () below.
8156  *
8157  * Returns: 0 on parse error.
8158  */
8159 static int
8160 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8161                              MonoTypeNameParse *info)
8162 {
8163         char *start, *p, *w, *last_point, *startn;
8164         int in_modifiers = 0;
8165         int isbyref = 0, rank = 0, isptr = 0;
8166
8167         start = p = w = name;
8168
8169         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8170         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8171         info->name = info->name_space = NULL;
8172         info->nested = NULL;
8173         info->modifiers = NULL;
8174         info->type_arguments = NULL;
8175
8176         /* last_point separates the namespace from the name */
8177         last_point = NULL;
8178         /* Skips spaces */
8179         while (*p == ' ') p++, start++, w++, name++;
8180
8181         while (*p) {
8182                 switch (*p) {
8183                 case '+':
8184                         *p = 0; /* NULL terminate the name */
8185                         startn = p + 1;
8186                         info->nested = g_list_append (info->nested, startn);
8187                         /* we have parsed the nesting namespace + name */
8188                         if (info->name)
8189                                 break;
8190                         if (last_point) {
8191                                 info->name_space = start;
8192                                 *last_point = 0;
8193                                 info->name = last_point + 1;
8194                         } else {
8195                                 info->name_space = (char *)"";
8196                                 info->name = start;
8197                         }
8198                         break;
8199                 case '.':
8200                         last_point = p;
8201                         break;
8202                 case '\\':
8203                         ++p;
8204                         break;
8205                 case '&':
8206                 case '*':
8207                 case '[':
8208                 case ',':
8209                 case ']':
8210                         in_modifiers = 1;
8211                         break;
8212                 default:
8213                         break;
8214                 }
8215                 if (in_modifiers)
8216                         break;
8217                 // *w++ = *p++;
8218                 p++;
8219         }
8220         
8221         if (!info->name) {
8222                 if (last_point) {
8223                         info->name_space = start;
8224                         *last_point = 0;
8225                         info->name = last_point + 1;
8226                 } else {
8227                         info->name_space = (char *)"";
8228                         info->name = start;
8229                 }
8230         }
8231         while (*p) {
8232                 switch (*p) {
8233                 case '&':
8234                         if (isbyref) /* only one level allowed by the spec */
8235                                 return 0;
8236                         isbyref = 1;
8237                         isptr = 0;
8238                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8239                         *p++ = 0;
8240                         break;
8241                 case '*':
8242                         if (isbyref) /* pointer to ref not okay */
8243                                 return 0;
8244                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8245                         isptr = 1;
8246                         *p++ = 0;
8247                         break;
8248                 case '[':
8249                         if (isbyref) /* array of ref and generic ref are not okay */
8250                                 return 0;
8251                         //Decide if it's an array of a generic argument list
8252                         *p++ = 0;
8253
8254                         if (!*p) //XXX test
8255                                 return 0;
8256                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8257                                 isptr = 0;
8258                                 rank = 1;
8259                                 while (*p) {
8260                                         if (*p == ']')
8261                                                 break;
8262                                         if (*p == ',')
8263                                                 rank++;
8264                                         else if (*p == '*') /* '*' means unknown lower bound */
8265                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8266                                         else
8267                                                 return 0;
8268                                         ++p;
8269                                 }
8270                                 if (*p++ != ']')
8271                                         return 0;
8272                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8273                         } else {
8274                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8275                                         return 0;
8276                                 isptr = 0;
8277                                 info->type_arguments = g_ptr_array_new ();
8278                                 while (*p) {
8279                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8280                                         gboolean fqname = FALSE;
8281
8282                                         g_ptr_array_add (info->type_arguments, subinfo);
8283
8284                                         while (*p == ' ') p++;
8285                                         if (*p == '[') {
8286                                                 p++;
8287                                                 fqname = TRUE;
8288                                         }
8289
8290                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8291                                                 return 0;
8292
8293                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8294                                         if (fqname && (*p != ']')) {
8295                                                 char *aname;
8296
8297                                                 if (*p != ',')
8298                                                         return 0;
8299                                                 *p++ = 0;
8300
8301                                                 aname = p;
8302                                                 while (*p && (*p != ']'))
8303                                                         p++;
8304
8305                                                 if (*p != ']')
8306                                                         return 0;
8307
8308                                                 *p++ = 0;
8309                                                 while (*aname) {
8310                                                         if (g_ascii_isspace (*aname)) {
8311                                                                 ++aname;
8312                                                                 continue;
8313                                                         }
8314                                                         break;
8315                                                 }
8316                                                 if (!*aname ||
8317                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8318                                                         return 0;
8319                                         } else if (fqname && (*p == ']')) {
8320                                                 *p++ = 0;
8321                                         }
8322                                         if (*p == ']') {
8323                                                 *p++ = 0;
8324                                                 break;
8325                                         } else if (!*p) {
8326                                                 return 0;
8327                                         }
8328                                         *p++ = 0;
8329                                 }
8330                         }
8331                         break;
8332                 case ']':
8333                         if (is_recursed)
8334                                 goto end;
8335                         return 0;
8336                 case ',':
8337                         if (is_recursed)
8338                                 goto end;
8339                         *p++ = 0;
8340                         while (*p) {
8341                                 if (g_ascii_isspace (*p)) {
8342                                         ++p;
8343                                         continue;
8344                                 }
8345                                 break;
8346                         }
8347                         if (!*p)
8348                                 return 0; /* missing assembly name */
8349                         if (!assembly_name_to_aname (&info->assembly, p))
8350                                 return 0;
8351                         break;
8352                 default:
8353                         return 0;
8354                 }
8355                 if (info->assembly.name)
8356                         break;
8357         }
8358         // *w = 0; /* terminate class name */
8359  end:
8360         if (!info->name || !*info->name)
8361                 return 0;
8362         if (endptr)
8363                 *endptr = p;
8364         /* add other consistency checks */
8365         return 1;
8366 }
8367
8368
8369 /**
8370  * mono_identifier_unescape_type_name_chars:
8371  * @identifier: the display name of a mono type
8372  *
8373  * Returns:
8374  *  The name in internal form, that is without escaping backslashes.
8375  *
8376  *  The string is modified in place!
8377  */
8378 char*
8379 mono_identifier_unescape_type_name_chars(char* identifier)
8380 {
8381         char *w, *r;
8382         if (!identifier)
8383                 return NULL;
8384         for (w = r = identifier; *r != 0; r++)
8385         {
8386                 char c = *r;
8387                 if (c == '\\') {
8388                         r++;
8389                         if (*r == 0)
8390                                 break;
8391                         c = *r;
8392                 }
8393                 *w = c;
8394                 w++;
8395         }
8396         if (w != r)
8397                 *w = 0;
8398         return identifier;
8399 }
8400
8401 void
8402 mono_identifier_unescape_info (MonoTypeNameParse* info);
8403
8404 static void
8405 unescape_each_type_argument(void* data, void* user_data)
8406 {
8407         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8408         mono_identifier_unescape_info (info);
8409 }
8410
8411 static void
8412 unescape_each_nested_name (void* data, void* user_data)
8413 {
8414         char* nested_name = (char*) data;
8415         mono_identifier_unescape_type_name_chars(nested_name);
8416 }
8417
8418 /**
8419  * mono_identifier_unescape_info:
8420  *
8421  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8422  *
8423  * Returns: nothing.
8424  *
8425  * Destructively updates the info by unescaping the identifiers that
8426  * comprise the type namespace, name, nested types (if any) and
8427  * generic type arguments (if any).
8428  *
8429  * The resulting info has the names in internal form.
8430  *
8431  */
8432 void
8433 mono_identifier_unescape_info (MonoTypeNameParse *info)
8434 {
8435         if (!info)
8436                 return;
8437         mono_identifier_unescape_type_name_chars(info->name_space);
8438         mono_identifier_unescape_type_name_chars(info->name);
8439         // but don't escape info->assembly
8440         if (info->type_arguments)
8441                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8442         if (info->nested)
8443                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8444 }
8445
8446 int
8447 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8448 {
8449         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8450         if (ok) {
8451                 mono_identifier_unescape_info (info);
8452         }
8453         return ok;
8454 }
8455
8456 static MonoType*
8457 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8458 {
8459         gboolean type_resolve = FALSE;
8460         MonoType *type;
8461         MonoImage *rootimage = image;
8462
8463         mono_error_init (error);
8464
8465         if (info->assembly.name) {
8466                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8467                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8468                         /* 
8469                          * This could happen in the AOT compiler case when the search hook is not
8470                          * installed.
8471                          */
8472                         assembly = image->assembly;
8473                 if (!assembly) {
8474                         /* then we must load the assembly ourselve - see #60439 */
8475                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8476                         if (!assembly)
8477                                 return NULL;
8478                 }
8479                 image = assembly->image;
8480         } else if (!image) {
8481                 image = mono_defaults.corlib;
8482         }
8483
8484         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8485         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8486                 mono_error_cleanup (error);
8487                 image = mono_defaults.corlib;
8488                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8489         }
8490
8491         return type;
8492 }
8493
8494 /**
8495  * mono_reflection_get_type_internal:
8496  *
8497  * Returns: may return NULL on success, sets error on failure.
8498  */
8499 static MonoType*
8500 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8501 {
8502         MonoClass *klass;
8503         GList *mod;
8504         int modval;
8505         gboolean bounded = FALSE;
8506         
8507         mono_error_init (error);
8508         if (!image)
8509                 image = mono_defaults.corlib;
8510
8511         if (!rootimage)
8512                 rootimage = mono_defaults.corlib;
8513
8514         if (ignorecase)
8515                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8516         else
8517                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8518
8519         if (!klass)
8520                 return NULL;
8521
8522         for (mod = info->nested; mod; mod = mod->next) {
8523                 gpointer iter = NULL;
8524                 MonoClass *parent;
8525
8526                 parent = klass;
8527                 mono_class_init (parent);
8528
8529                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8530                         char *lastp;
8531                         char *nested_name, *nested_nspace;
8532                         gboolean match = TRUE;
8533
8534                         lastp = strrchr ((const char *)mod->data, '.');
8535                         if (lastp) {
8536                                 /* Nested classes can have namespaces */
8537                                 int nspace_len;
8538
8539                                 nested_name = g_strdup (lastp + 1);
8540                                 nspace_len = lastp - (char*)mod->data;
8541                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8542                                 memcpy (nested_nspace, mod->data, nspace_len);
8543                                 nested_nspace [nspace_len] = '\0';
8544
8545                         } else {
8546                                 nested_name = (char *)mod->data;
8547                                 nested_nspace = NULL;
8548                         }
8549
8550                         if (nested_nspace) {
8551                                 if (ignorecase) {
8552                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8553                                                 match = FALSE;
8554                                 } else {
8555                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8556                                                 match = FALSE;
8557                                 }
8558                         }
8559                         if (match) {
8560                                 if (ignorecase) {
8561                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8562                                                 match = FALSE;
8563                                 } else {
8564                                         if (strcmp (klass->name, nested_name) != 0)
8565                                                 match = FALSE;
8566                                 }
8567                         }
8568                         if (lastp) {
8569                                 g_free (nested_name);
8570                                 g_free (nested_nspace);
8571                         }
8572                         if (match)
8573                                 break;
8574                 }
8575
8576                 if (!klass)
8577                         break;
8578         }
8579         if (!klass)
8580                 return NULL;
8581
8582         if (info->type_arguments) {
8583                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8584                 MonoReflectionType *the_type;
8585                 MonoType *instance;
8586                 int i;
8587
8588                 for (i = 0; i < info->type_arguments->len; i++) {
8589                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8590
8591                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8592                         if (!type_args [i]) {
8593                                 g_free (type_args);
8594                                 return NULL;
8595                         }
8596                 }
8597
8598                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8599                 if (!the_type)
8600                         return NULL;
8601
8602                 instance = mono_reflection_bind_generic_parameters (
8603                         the_type, info->type_arguments->len, type_args, error);
8604
8605                 g_free (type_args);
8606                 if (!instance)
8607                         return NULL;
8608
8609                 klass = mono_class_from_mono_type (instance);
8610         }
8611
8612         for (mod = info->modifiers; mod; mod = mod->next) {
8613                 modval = GPOINTER_TO_UINT (mod->data);
8614                 if (!modval) { /* byref: must be last modifier */
8615                         return &klass->this_arg;
8616                 } else if (modval == -1) {
8617                         klass = mono_ptr_class_get (&klass->byval_arg);
8618                 } else if (modval == -2) {
8619                         bounded = TRUE;
8620                 } else { /* array rank */
8621                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8622                 }
8623         }
8624
8625         return &klass->byval_arg;
8626 }
8627
8628 /*
8629  * mono_reflection_get_type:
8630  * @image: a metadata context
8631  * @info: type description structure
8632  * @ignorecase: flag for case-insensitive string compares
8633  * @type_resolve: whenever type resolve was already tried
8634  *
8635  * Build a MonoType from the type description in @info.
8636  * 
8637  */
8638
8639 MonoType*
8640 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8641         MonoError error;
8642         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8643         mono_error_cleanup (&error);
8644         return result;
8645 }
8646
8647 /**
8648  * mono_reflection_get_type_checked:
8649  * @rootimage: the image of the currently active managed caller
8650  * @image: a metadata context
8651  * @info: type description structure
8652  * @ignorecase: flag for case-insensitive string compares
8653  * @type_resolve: whenever type resolve was already tried
8654  * @error: set on error.
8655  *
8656  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8657  *
8658  */
8659 MonoType*
8660 mono_reflection_get_type_checked (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8661         mono_error_init (error);
8662         return mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, type_resolve, error);
8663 }
8664
8665
8666 static MonoType*
8667 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8668 {
8669         MonoReflectionAssemblyBuilder *abuilder;
8670         MonoType *type;
8671         int i;
8672
8673         mono_error_init (error);
8674         g_assert (assembly_is_dynamic (assembly));
8675         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8676         if (!abuilder)
8677                 return NULL;
8678
8679         /* Enumerate all modules */
8680
8681         type = NULL;
8682         if (abuilder->modules) {
8683                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8684                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8685                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8686                         if (type)
8687                                 break;
8688                         if (!mono_error_ok (error))
8689                                 return NULL;
8690                 }
8691         }
8692
8693         if (!type && abuilder->loaded_modules) {
8694                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8695                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8696                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8697                         if (type)
8698                                 break;
8699                         if (!mono_error_ok (error))
8700                                 return NULL;
8701                 }
8702         }
8703
8704         return type;
8705 }
8706         
8707 MonoType*
8708 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8709 {
8710         MonoType *type;
8711         MonoReflectionAssembly *assembly;
8712         GString *fullName;
8713         GList *mod;
8714
8715         mono_error_init (error);
8716
8717         if (image && image_is_dynamic (image))
8718                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8719         else {
8720                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8721         }
8722         return_val_if_nok (error, NULL);
8723
8724         if (type)
8725                 return type;
8726         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8727                 return NULL;
8728
8729         if (type_resolve) {
8730                 if (*type_resolve) 
8731                         return NULL;
8732                 else
8733                         *type_resolve = TRUE;
8734         }
8735         
8736         /* Reconstruct the type name */
8737         fullName = g_string_new ("");
8738         if (info->name_space && (info->name_space [0] != '\0'))
8739                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8740         else
8741                 g_string_printf (fullName, "%s", info->name);
8742         for (mod = info->nested; mod; mod = mod->next)
8743                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8744
8745         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8746         if (!is_ok (error)) {
8747                 g_string_free (fullName, TRUE);
8748                 return NULL;
8749         }
8750
8751         if (assembly) {
8752                 if (assembly_is_dynamic (assembly->assembly))
8753                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8754                                                                           info, ignorecase, error);
8755                 else
8756                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8757                                                                   info, ignorecase, error);
8758         }
8759         g_string_free (fullName, TRUE);
8760         return_val_if_nok (error, NULL);
8761         return type;
8762 }
8763
8764 void
8765 mono_reflection_free_type_info (MonoTypeNameParse *info)
8766 {
8767         g_list_free (info->modifiers);
8768         g_list_free (info->nested);
8769
8770         if (info->type_arguments) {
8771                 int i;
8772
8773                 for (i = 0; i < info->type_arguments->len; i++) {
8774                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8775
8776                         mono_reflection_free_type_info (subinfo);
8777                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8778                         g_free (subinfo);
8779                 }
8780
8781                 g_ptr_array_free (info->type_arguments, TRUE);
8782         }
8783 }
8784
8785 /*
8786  * mono_reflection_type_from_name:
8787  * @name: type name.
8788  * @image: a metadata context (can be NULL).
8789  *
8790  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8791  * it defaults to get the type from @image or, if @image is NULL or loading
8792  * from it fails, uses corlib.
8793  * 
8794  */
8795 MonoType*
8796 mono_reflection_type_from_name (char *name, MonoImage *image)
8797 {
8798         MonoError error;
8799         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8800         mono_error_cleanup (&error);
8801         return result;
8802 }
8803
8804 /**
8805  * mono_reflection_type_from_name_checked:
8806  * @name: type name.
8807  * @image: a metadata context (can be NULL).
8808  * @error: set on errror.
8809  *
8810  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8811  * it defaults to get the type from @image or, if @image is NULL or loading
8812  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8813  * 
8814  */
8815 MonoType*
8816 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8817 {
8818         MonoType *type = NULL;
8819         MonoTypeNameParse info;
8820         char *tmp;
8821
8822         mono_error_init (error);
8823         /* Make a copy since parse_type modifies its argument */
8824         tmp = g_strdup (name);
8825         
8826         /*g_print ("requested type %s\n", str);*/
8827         if (mono_reflection_parse_type (tmp, &info)) {
8828                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8829                 if (!is_ok (error)) {
8830                         g_free (tmp);
8831                         mono_reflection_free_type_info (&info);
8832                         return NULL;
8833                 }
8834         }
8835
8836         g_free (tmp);
8837         mono_reflection_free_type_info (&info);
8838         return type;
8839 }
8840
8841 /*
8842  * mono_reflection_get_token:
8843  *
8844  *   Return the metadata token of OBJ which should be an object
8845  * representing a metadata element.
8846  */
8847 guint32
8848 mono_reflection_get_token (MonoObject *obj)
8849 {
8850         MonoError error;
8851         guint32 result = mono_reflection_get_token_checked (obj, &error);
8852         mono_error_assert_ok (&error);
8853         return result;
8854 }
8855
8856 /**
8857  * mono_reflection_get_token_checked:
8858  * @obj: the object
8859  * @error: set on error
8860  *
8861  *   Return the metadata token of @obj which should be an object
8862  * representing a metadata element.  On failure sets @error.
8863  */
8864 guint32
8865 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8866 {
8867         MonoClass *klass;
8868         guint32 token = 0;
8869
8870         mono_error_init (error);
8871
8872         klass = obj->vtable->klass;
8873
8874         if (strcmp (klass->name, "MethodBuilder") == 0) {
8875                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8876
8877                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8878         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8879                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8880
8881                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8882         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8883                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8884
8885                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8886         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8887                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8888                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8889         } else if (strcmp (klass->name, "MonoType") == 0) {
8890                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8891                 return_val_if_nok (error, 0);
8892                 MonoClass *mc = mono_class_from_mono_type (type);
8893                 if (!mono_class_init (mc)) {
8894                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8895                         return 0;
8896                 }
8897
8898                 token = mc->type_token;
8899         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8900                    strcmp (klass->name, "MonoMethod") == 0 ||
8901                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8902                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8903                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8904                 if (m->method->is_inflated) {
8905                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8906                         return inflated->declaring->token;
8907                 } else {
8908                         token = m->method->token;
8909                 }
8910         } else if (strcmp (klass->name, "MonoField") == 0) {
8911                 MonoReflectionField *f = (MonoReflectionField*)obj;
8912
8913                 if (is_field_on_inst (f->field)) {
8914                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8915
8916                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8917                                 int field_index = f->field - dgclass->fields;
8918                                 MonoObject *obj;
8919
8920                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8921                                 obj = dgclass->field_objects [field_index];
8922                                 return mono_reflection_get_token_checked (obj, error);
8923                         }
8924                 }
8925                 token = mono_class_get_field_token (f->field);
8926         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8927                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8928
8929                 token = mono_class_get_property_token (p->property);
8930         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8931                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8932
8933                 token = mono_class_get_event_token (p->event);
8934         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8935                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8936                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8937                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8938
8939                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8940         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8941                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8942
8943                 token = m->token;
8944         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8945                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8946         } else {
8947                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8948                                                 klass->name_space, klass->name);
8949                 return 0;
8950         }
8951
8952         return token;
8953 }
8954
8955 static MonoClass*
8956 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8957 {
8958         char *n;
8959         MonoType *t;
8960         int slen = mono_metadata_decode_value (p, &p);
8961
8962         mono_error_init (error);
8963
8964         n = (char *)g_memdup (p, slen + 1);
8965         n [slen] = 0;
8966         t = mono_reflection_type_from_name_checked (n, image, error);
8967         if (!t) {
8968                 char *msg = g_strdup (mono_error_get_message (error));
8969                 mono_error_cleanup (error);
8970                 /* We don't free n, it's consumed by mono_error */
8971                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8972                 g_free (msg);
8973                 return NULL;
8974         }
8975         g_free (n);
8976         p += slen;
8977         *end = p;
8978         return mono_class_from_mono_type (t);
8979 }
8980
8981 static void*
8982 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8983 {
8984         int slen, type = t->type;
8985         MonoClass *tklass = t->data.klass;
8986
8987         mono_error_init (error);
8988
8989 handle_enum:
8990         switch (type) {
8991         case MONO_TYPE_U1:
8992         case MONO_TYPE_I1:
8993         case MONO_TYPE_BOOLEAN: {
8994                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8995                 *bval = *p;
8996                 *end = p + 1;
8997                 return bval;
8998         }
8999         case MONO_TYPE_CHAR:
9000         case MONO_TYPE_U2:
9001         case MONO_TYPE_I2: {
9002                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
9003                 *val = read16 (p);
9004                 *end = p + 2;
9005                 return val;
9006         }
9007 #if SIZEOF_VOID_P == 4
9008         case MONO_TYPE_U:
9009         case MONO_TYPE_I:
9010 #endif
9011         case MONO_TYPE_R4:
9012         case MONO_TYPE_U4:
9013         case MONO_TYPE_I4: {
9014                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
9015                 *val = read32 (p);
9016                 *end = p + 4;
9017                 return val;
9018         }
9019 #if SIZEOF_VOID_P == 8
9020         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9021         case MONO_TYPE_I:
9022 #endif
9023         case MONO_TYPE_U8:
9024         case MONO_TYPE_I8: {
9025                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9026                 *val = read64 (p);
9027                 *end = p + 8;
9028                 return val;
9029         }
9030         case MONO_TYPE_R8: {
9031                 double *val = (double *)g_malloc (sizeof (double));
9032                 readr8 (p, val);
9033                 *end = p + 8;
9034                 return val;
9035         }
9036         case MONO_TYPE_VALUETYPE:
9037                 if (t->data.klass->enumtype) {
9038                         type = mono_class_enum_basetype (t->data.klass)->type;
9039                         goto handle_enum;
9040                 } else {
9041                         MonoClass *k =  t->data.klass;
9042                         
9043                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9044                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9045                                 *val = read64 (p);
9046                                 *end = p + 8;
9047                                 return val;
9048                         }
9049                 }
9050                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9051                 break;
9052                 
9053         case MONO_TYPE_STRING:
9054                 if (*p == (char)0xFF) {
9055                         *end = p + 1;
9056                         return NULL;
9057                 }
9058                 slen = mono_metadata_decode_value (p, &p);
9059                 *end = p + slen;
9060                 return mono_string_new_len (mono_domain_get (), p, slen);
9061         case MONO_TYPE_CLASS: {
9062                 MonoReflectionType *rt;
9063                 char *n;
9064                 MonoType *t;
9065                 if (*p == (char)0xFF) {
9066                         *end = p + 1;
9067                         return NULL;
9068                 }
9069 handle_type:
9070                 slen = mono_metadata_decode_value (p, &p);
9071                 n = (char *)g_memdup (p, slen + 1);
9072                 n [slen] = 0;
9073                 t = mono_reflection_type_from_name_checked (n, image, error);
9074                 if (!t) {
9075                         char *msg = g_strdup (mono_error_get_message (error));
9076                         mono_error_cleanup (error);
9077                         /* We don't free n, it's consumed by mono_error */
9078                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9079                         g_free (msg);
9080                         return NULL;
9081                 }
9082                 g_free (n);
9083                 *end = p + slen;
9084
9085                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9086                 if (!mono_error_ok (error))
9087                         return NULL;
9088
9089                 return rt;
9090         }
9091         case MONO_TYPE_OBJECT: {
9092                 char subt = *p++;
9093                 MonoObject *obj;
9094                 MonoClass *subc = NULL;
9095                 void *val;
9096
9097                 if (subt == 0x50) {
9098                         goto handle_type;
9099                 } else if (subt == 0x0E) {
9100                         type = MONO_TYPE_STRING;
9101                         goto handle_enum;
9102                 } else if (subt == 0x1D) {
9103                         MonoType simple_type = {{0}};
9104                         int etype = *p;
9105                         p ++;
9106
9107                         type = MONO_TYPE_SZARRAY;
9108                         if (etype == 0x50) {
9109                                 tklass = mono_defaults.systemtype_class;
9110                         } else if (etype == 0x55) {
9111                                 tklass = load_cattr_enum_type (image, p, &p, error);
9112                                 if (!mono_error_ok (error))
9113                                         return NULL;
9114                         } else {
9115                                 if (etype == 0x51)
9116                                         /* See Partition II, Appendix B3 */
9117                                         etype = MONO_TYPE_OBJECT;
9118                                 simple_type.type = (MonoTypeEnum)etype;
9119                                 tklass = mono_class_from_mono_type (&simple_type);
9120                         }
9121                         goto handle_enum;
9122                 } else if (subt == 0x55) {
9123                         char *n;
9124                         MonoType *t;
9125                         slen = mono_metadata_decode_value (p, &p);
9126                         n = (char *)g_memdup (p, slen + 1);
9127                         n [slen] = 0;
9128                         t = mono_reflection_type_from_name_checked (n, image, error);
9129                         if (!t) {
9130                                 char *msg = g_strdup (mono_error_get_message (error));
9131                                 mono_error_cleanup (error);
9132                                 /* We don't free n, it's consumed by mono_error */
9133                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9134                                 g_free (msg);
9135                                 return NULL;
9136                         }
9137                         g_free (n);
9138                         p += slen;
9139                         subc = mono_class_from_mono_type (t);
9140                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9141                         MonoType simple_type = {{0}};
9142                         simple_type.type = (MonoTypeEnum)subt;
9143                         subc = mono_class_from_mono_type (&simple_type);
9144                 } else {
9145                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9146                 }
9147                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9148                 obj = NULL;
9149                 if (mono_error_ok (error)) {
9150                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9151                         g_assert (!subc->has_references);
9152                         if (mono_error_ok (error))
9153                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9154                 }
9155
9156                 g_free (val);
9157                 return obj;
9158         }
9159         case MONO_TYPE_SZARRAY: {
9160                 MonoArray *arr;
9161                 guint32 i, alen, basetype;
9162                 alen = read32 (p);
9163                 p += 4;
9164                 if (alen == 0xffffffff) {
9165                         *end = p;
9166                         return NULL;
9167                 }
9168                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9169                 basetype = tklass->byval_arg.type;
9170                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9171                         basetype = mono_class_enum_basetype (tklass)->type;
9172                 switch (basetype)
9173                 {
9174                         case MONO_TYPE_U1:
9175                         case MONO_TYPE_I1:
9176                         case MONO_TYPE_BOOLEAN:
9177                                 for (i = 0; i < alen; i++) {
9178                                         MonoBoolean val = *p++;
9179                                         mono_array_set (arr, MonoBoolean, i, val);
9180                                 }
9181                                 break;
9182                         case MONO_TYPE_CHAR:
9183                         case MONO_TYPE_U2:
9184                         case MONO_TYPE_I2:
9185                                 for (i = 0; i < alen; i++) {
9186                                         guint16 val = read16 (p);
9187                                         mono_array_set (arr, guint16, i, val);
9188                                         p += 2;
9189                                 }
9190                                 break;
9191                         case MONO_TYPE_R4:
9192                         case MONO_TYPE_U4:
9193                         case MONO_TYPE_I4:
9194                                 for (i = 0; i < alen; i++) {
9195                                         guint32 val = read32 (p);
9196                                         mono_array_set (arr, guint32, i, val);
9197                                         p += 4;
9198                                 }
9199                                 break;
9200                         case MONO_TYPE_R8:
9201                                 for (i = 0; i < alen; i++) {
9202                                         double val;
9203                                         readr8 (p, &val);
9204                                         mono_array_set (arr, double, i, val);
9205                                         p += 8;
9206                                 }
9207                                 break;
9208                         case MONO_TYPE_U8:
9209                         case MONO_TYPE_I8:
9210                                 for (i = 0; i < alen; i++) {
9211                                         guint64 val = read64 (p);
9212                                         mono_array_set (arr, guint64, i, val);
9213                                         p += 8;
9214                                 }
9215                                 break;
9216                         case MONO_TYPE_CLASS:
9217                         case MONO_TYPE_OBJECT:
9218                         case MONO_TYPE_STRING:
9219                         case MONO_TYPE_SZARRAY:
9220                                 for (i = 0; i < alen; i++) {
9221                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9222                                         if (!mono_error_ok (error))
9223                                                 return NULL;
9224                                         mono_array_setref (arr, i, item);
9225                                 }
9226                                 break;
9227                         default:
9228                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9229                 }
9230                 *end=p;
9231                 return arr;
9232         }
9233         default:
9234                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9235         }
9236         return NULL;
9237 }
9238
9239 static MonoObject*
9240 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9241 {
9242         mono_error_init (error);
9243
9244         gboolean is_ref = type_is_reference (t);
9245
9246         void *val = load_cattr_value (image, t, p, end, error);
9247         if (!is_ok (error)) {
9248                 if (is_ref)
9249                         g_free (val);
9250                 return NULL;
9251         }
9252
9253         if (is_ref)
9254                 return (MonoObject*)val;
9255
9256         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9257         g_free (val);
9258         return boxed;
9259 }
9260
9261 static MonoObject*
9262 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9263 {
9264         static MonoMethod *ctor;
9265         MonoObject *retval;
9266         void *params [2], *unboxed;
9267
9268         mono_error_init (error);
9269
9270         if (!ctor)
9271                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9272         
9273         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9274         return_val_if_nok (error, NULL);
9275
9276         params [1] = val;
9277         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9278         return_val_if_nok (error, NULL);
9279         unboxed = mono_object_unbox (retval);
9280
9281         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9282         return_val_if_nok (error, NULL);
9283
9284         return retval;
9285 }
9286
9287 static MonoObject*
9288 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9289 {
9290         static MonoMethod *ctor;
9291         MonoObject *retval;
9292         void *unboxed, *params [2];
9293
9294         mono_error_init (error);
9295
9296         if (!ctor)
9297                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9298
9299         params [0] = minfo;
9300         params [1] = typedarg;
9301         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9302         return_val_if_nok (error, NULL);
9303
9304         unboxed = mono_object_unbox (retval);
9305
9306         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9307         return_val_if_nok (error, NULL);
9308
9309         return retval;
9310 }
9311
9312 static gboolean
9313 type_is_reference (MonoType *type)
9314 {
9315         switch (type->type) {
9316         case MONO_TYPE_BOOLEAN:
9317         case MONO_TYPE_CHAR:
9318         case MONO_TYPE_U:
9319         case MONO_TYPE_I:
9320         case MONO_TYPE_U1:
9321         case MONO_TYPE_I1:
9322         case MONO_TYPE_U2:
9323         case MONO_TYPE_I2:
9324         case MONO_TYPE_U4:
9325         case MONO_TYPE_I4:
9326         case MONO_TYPE_U8:
9327         case MONO_TYPE_I8:
9328         case MONO_TYPE_R8:
9329         case MONO_TYPE_R4:
9330         case MONO_TYPE_VALUETYPE:
9331                 return FALSE;
9332         default:
9333                 return TRUE;
9334         }
9335 }
9336
9337 static void
9338 free_param_data (MonoMethodSignature *sig, void **params) {
9339         int i;
9340         for (i = 0; i < sig->param_count; ++i) {
9341                 if (!type_is_reference (sig->params [i]))
9342                         g_free (params [i]);
9343         }
9344 }
9345
9346 /*
9347  * Find the field index in the metadata FieldDef table.
9348  */
9349 static guint32
9350 find_field_index (MonoClass *klass, MonoClassField *field) {
9351         int i;
9352
9353         for (i = 0; i < klass->field.count; ++i) {
9354                 if (field == &klass->fields [i])
9355                         return klass->field.first + 1 + i;
9356         }
9357         return 0;
9358 }
9359
9360 /*
9361  * Find the property index in the metadata Property table.
9362  */
9363 static guint32
9364 find_property_index (MonoClass *klass, MonoProperty *property) {
9365         int i;
9366
9367         for (i = 0; i < klass->ext->property.count; ++i) {
9368                 if (property == &klass->ext->properties [i])
9369                         return klass->ext->property.first + 1 + i;
9370         }
9371         return 0;
9372 }
9373
9374 /*
9375  * Find the event index in the metadata Event table.
9376  */
9377 static guint32
9378 find_event_index (MonoClass *klass, MonoEvent *event) {
9379         int i;
9380
9381         for (i = 0; i < klass->ext->event.count; ++i) {
9382                 if (event == &klass->ext->events [i])
9383                         return klass->ext->event.first + 1 + i;
9384         }
9385         return 0;
9386 }
9387
9388 static MonoObject*
9389 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9390 {
9391         const char *p = (const char*)data;
9392         const char *named;
9393         guint32 i, j, num_named;
9394         MonoObject *attr;
9395         void *params_buf [32];
9396         void **params = NULL;
9397         MonoMethodSignature *sig;
9398
9399         mono_error_init (error);
9400
9401         mono_class_init (method->klass);
9402
9403         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9404                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9405                 return NULL;
9406         }
9407
9408         if (len == 0) {
9409                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9410                 if (!mono_error_ok (error)) return NULL;
9411
9412                 mono_runtime_invoke_checked (method, attr, NULL, error);
9413                 if (!mono_error_ok (error))
9414                         return NULL;
9415
9416                 return attr;
9417         }
9418
9419         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9420                 return NULL;
9421
9422         /*g_print ("got attr %s\n", method->klass->name);*/
9423
9424         sig = mono_method_signature (method);
9425         if (sig->param_count < 32) {
9426                 params = params_buf;
9427                 memset (params, 0, sizeof (void*) * sig->param_count);
9428         } else {
9429                 /* Allocate using GC so it gets GC tracking */
9430                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9431         }
9432
9433         /* skip prolog */
9434         p += 2;
9435         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9436                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9437                 if (!mono_error_ok (error))
9438                         goto fail;
9439         }
9440
9441         named = p;
9442         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9443         if (!mono_error_ok (error)) goto fail;
9444
9445         MonoObject *exc = NULL;
9446         mono_runtime_try_invoke (method, attr, params, &exc, error);
9447         if (!mono_error_ok (error))
9448                 goto fail;
9449         if (exc) {
9450                 mono_error_set_exception_instance (error, (MonoException*)exc);
9451                 goto fail;
9452         }
9453
9454         num_named = read16 (named);
9455         named += 2;
9456         for (j = 0; j < num_named; j++) {
9457                 gint name_len;
9458                 char *name, named_type, data_type;
9459                 named_type = *named++;
9460                 data_type = *named++; /* type of data */
9461                 if (data_type == MONO_TYPE_SZARRAY)
9462                         data_type = *named++;
9463                 if (data_type == MONO_TYPE_ENUM) {
9464                         gint type_len;
9465                         char *type_name;
9466                         type_len = mono_metadata_decode_blob_size (named, &named);
9467                         type_name = (char *)g_malloc (type_len + 1);
9468                         memcpy (type_name, named, type_len);
9469                         type_name [type_len] = 0;
9470                         named += type_len;
9471                         /* FIXME: lookup the type and check type consistency */
9472                         g_free (type_name);
9473                 }
9474                 name_len = mono_metadata_decode_blob_size (named, &named);
9475                 name = (char *)g_malloc (name_len + 1);
9476                 memcpy (name, named, name_len);
9477                 name [name_len] = 0;
9478                 named += name_len;
9479                 if (named_type == 0x53) {
9480                         MonoClassField *field;
9481                         void *val;
9482
9483                         /* how this fail is a blackbox */
9484                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9485                         if (!field) {
9486                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9487                                 g_free (name);
9488                                 goto fail;
9489                         }
9490
9491                         val = load_cattr_value (image, field->type, named, &named, error);
9492                         if (!mono_error_ok (error)) {
9493                                 g_free (name);
9494                                 if (!type_is_reference (field->type))
9495                                         g_free (val);
9496                                 goto fail;
9497                         }
9498
9499                         mono_field_set_value (attr, field, val);
9500                         if (!type_is_reference (field->type))
9501                                 g_free (val);
9502                 } else if (named_type == 0x54) {
9503                         MonoProperty *prop;
9504                         void *pparams [1];
9505                         MonoType *prop_type;
9506
9507                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9508
9509                         if (!prop) {
9510                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9511                                 g_free (name);
9512                                 goto fail;
9513                         }
9514
9515                         if (!prop->set) {
9516                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9517                                 g_free (name);
9518                                 goto fail;
9519                         }
9520
9521                         /* can we have more that 1 arg in a custom attr named property? */
9522                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9523                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9524
9525                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9526                         if (!mono_error_ok (error)) {
9527                                 g_free (name);
9528                                 if (!type_is_reference (prop_type))
9529                                         g_free (pparams [0]);
9530                                 goto fail;
9531                         }
9532
9533
9534                         mono_property_set_value (prop, attr, pparams, NULL);
9535                         if (!type_is_reference (prop_type))
9536                                 g_free (pparams [0]);
9537                 }
9538                 g_free (name);
9539         }
9540
9541         free_param_data (method->signature, params);
9542         if (params != params_buf)
9543                 mono_gc_free_fixed (params);
9544
9545         return attr;
9546
9547 fail:
9548         free_param_data (method->signature, params);
9549         if (params != params_buf)
9550                 mono_gc_free_fixed (params);
9551         return NULL;
9552 }
9553         
9554 /*
9555  * mono_reflection_create_custom_attr_data_args:
9556  *
9557  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9558  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9559  * NAMED_ARG_INFO will contain information about the named arguments.
9560  */
9561 void
9562 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)
9563 {
9564         MonoArray *typedargs, *namedargs;
9565         MonoClass *attrklass;
9566         MonoDomain *domain;
9567         const char *p = (const char*)data;
9568         const char *named;
9569         guint32 i, j, num_named;
9570         CattrNamedArg *arginfo = NULL;
9571
9572         *typed_args = NULL;
9573         *named_args = NULL;
9574         *named_arg_info = NULL;
9575
9576         mono_error_init (error);
9577
9578         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9579                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9580                 return;
9581         }
9582
9583         mono_class_init (method->klass);
9584         
9585         domain = mono_domain_get ();
9586
9587         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9588                 return;
9589
9590         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9591         
9592         /* skip prolog */
9593         p += 2;
9594         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9595                 MonoObject *obj;
9596
9597                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9598                 return_if_nok (error);
9599                 mono_array_setref (typedargs, i, obj);
9600         }
9601
9602         named = p;
9603         num_named = read16 (named);
9604         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9605         named += 2;
9606         attrklass = method->klass;
9607
9608         arginfo = g_new0 (CattrNamedArg, num_named);
9609         *named_arg_info = arginfo;
9610
9611         for (j = 0; j < num_named; j++) {
9612                 gint name_len;
9613                 char *name, named_type, data_type;
9614                 named_type = *named++;
9615                 data_type = *named++; /* type of data */
9616                 if (data_type == MONO_TYPE_SZARRAY)
9617                         data_type = *named++;
9618                 if (data_type == MONO_TYPE_ENUM) {
9619                         gint type_len;
9620                         char *type_name;
9621                         type_len = mono_metadata_decode_blob_size (named, &named);
9622                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9623                                 goto fail;
9624
9625                         type_name = (char *)g_malloc (type_len + 1);
9626                         memcpy (type_name, named, type_len);
9627                         type_name [type_len] = 0;
9628                         named += type_len;
9629                         /* FIXME: lookup the type and check type consistency */
9630                         g_free (type_name);
9631                 }
9632                 name_len = mono_metadata_decode_blob_size (named, &named);
9633                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9634                         goto fail;
9635                 name = (char *)g_malloc (name_len + 1);
9636                 memcpy (name, named, name_len);
9637                 name [name_len] = 0;
9638                 named += name_len;
9639                 if (named_type == 0x53) {
9640                         MonoObject *obj;
9641                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9642
9643                         if (!field) {
9644                                 g_free (name);
9645                                 goto fail;
9646                         }
9647
9648                         arginfo [j].type = field->type;
9649                         arginfo [j].field = field;
9650
9651                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9652                         if (!is_ok (error)) {
9653                                 g_free (name);
9654                                 return;
9655                         }
9656                         mono_array_setref (namedargs, j, obj);
9657
9658                 } else if (named_type == 0x54) {
9659                         MonoObject *obj;
9660                         MonoType *prop_type;
9661                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9662
9663                         if (!prop || !prop->set) {
9664                                 g_free (name);
9665                                 goto fail;
9666                         }
9667
9668                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9669                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9670
9671                         arginfo [j].type = prop_type;
9672                         arginfo [j].prop = prop;
9673
9674                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9675                         if (!is_ok (error)) {
9676                                 g_free (name);
9677                                 return;
9678                         }
9679                         mono_array_setref (namedargs, j, obj);
9680                 }
9681                 g_free (name);
9682         }
9683
9684         *typed_args = typedargs;
9685         *named_args = namedargs;
9686         return;
9687 fail:
9688         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9689         g_free (arginfo);
9690         *named_arg_info = NULL;
9691 }
9692
9693 static gboolean
9694 reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args, MonoError *error)
9695 {
9696         MonoDomain *domain;
9697         MonoArray *typedargs, *namedargs;
9698         MonoImage *image;
9699         MonoMethod *method;
9700         CattrNamedArg *arginfo = NULL;
9701         int i;
9702
9703         mono_error_init (error);
9704
9705         *ctor_args = NULL;
9706         *named_args = NULL;
9707
9708         if (len == 0)
9709                 return TRUE;
9710
9711         image = assembly->assembly->image;
9712         method = ref_method->method;
9713         domain = mono_object_domain (ref_method);
9714
9715         if (!mono_class_init (method->klass)) {
9716                 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (method->klass));
9717                 goto leave;
9718         }
9719
9720         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, error);
9721         if (!is_ok (error))
9722                 goto leave;
9723
9724         if (!typedargs || !namedargs)
9725                 goto leave;
9726
9727         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9728                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9729                 MonoObject *typedarg;
9730
9731                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, error);
9732                 if (!is_ok (error))
9733                         goto leave;
9734                 mono_array_setref (typedargs, i, typedarg);
9735         }
9736
9737         for (i = 0; i < mono_array_length (namedargs); ++i) {
9738                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9739                 MonoObject *typedarg, *namedarg, *minfo;
9740
9741                 if (arginfo [i].prop) {
9742                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, error);
9743                         if (!minfo)
9744                                 goto leave;
9745                 } else {
9746                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, error);
9747                         if (!is_ok (error))
9748                                 goto leave;
9749                 }
9750
9751                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, error);
9752                 if (!is_ok (error))
9753                         goto leave;
9754                 namedarg = create_cattr_named_arg (minfo, typedarg, error);
9755                 if (!is_ok (error))
9756                         goto leave;
9757
9758                 mono_array_setref (namedargs, i, namedarg);
9759         }
9760
9761         *ctor_args = typedargs;
9762         *named_args = namedargs;
9763
9764 leave:
9765         g_free (arginfo);
9766         return mono_error_ok (error);
9767 }
9768
9769 void
9770 ves_icall_System_Reflection_CustomAttributeData_ResolveArgumentsInternal (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9771 {
9772         MonoError error;
9773         (void) reflection_resolve_custom_attribute_data (ref_method, assembly, data, len, ctor_args, named_args, &error);
9774         mono_error_set_pending_exception (&error);
9775 }
9776
9777 static MonoObject*
9778 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9779 {
9780         static MonoMethod *ctor;
9781
9782         MonoDomain *domain;
9783         MonoObject *attr;
9784         void *params [4];
9785
9786         mono_error_init (error);
9787
9788         g_assert (image->assembly);
9789
9790         if (!ctor)
9791                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9792
9793         domain = mono_domain_get ();
9794         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9795         return_val_if_nok (error, NULL);
9796         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9797         return_val_if_nok (error, NULL);
9798         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9799         return_val_if_nok (error, NULL);
9800         params [2] = (gpointer)&cattr->data;
9801         params [3] = &cattr->data_size;
9802
9803         mono_runtime_invoke_checked (ctor, attr, params, error);
9804         return_val_if_nok (error, NULL);
9805         return attr;
9806 }
9807
9808 static MonoArray*
9809 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9810 {
9811         MonoArray *result;
9812         MonoObject *attr;
9813         int i, n;
9814
9815         mono_error_init (error);
9816
9817         n = 0;
9818         for (i = 0; i < cinfo->num_attrs; ++i) {
9819                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9820                         n ++;
9821         }
9822
9823         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9824         n = 0;
9825         for (i = 0; i < cinfo->num_attrs; ++i) {
9826                 if (!cinfo->attrs [i].ctor) {
9827                         /* The cattr type is not finished yet */
9828                         /* We should include the type name but cinfo doesn't contain it */
9829                         mono_error_set_type_load_name (error, NULL, NULL, "");
9830                         return NULL;
9831                 }
9832                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9833                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9834                         if (!mono_error_ok (error))
9835                                 return result;
9836                         mono_array_setref (result, n, attr);
9837                         n ++;
9838                 }
9839         }
9840         return result;
9841 }
9842
9843 MonoArray*
9844 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9845 {
9846         MonoError error;
9847         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9848         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9849
9850         return result;
9851 }
9852
9853 static MonoArray*
9854 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9855 {
9856         MonoArray *result;
9857         MonoObject *attr;
9858         int i;
9859         
9860         mono_error_init (error);
9861         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9862         for (i = 0; i < cinfo->num_attrs; ++i) {
9863                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9864                 return_val_if_nok (error, NULL);
9865                 mono_array_setref (result, i, attr);
9866         }
9867         return result;
9868 }
9869
9870 /**
9871  * mono_custom_attrs_from_index:
9872  *
9873  * Returns: NULL if no attributes are found or if a loading error occurs.
9874  */
9875 MonoCustomAttrInfo*
9876 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9877 {
9878         MonoError error;
9879         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9880         mono_error_cleanup (&error);
9881         return result;
9882 }
9883 /**
9884  * mono_custom_attrs_from_index_checked:
9885  *
9886  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9887  */
9888 MonoCustomAttrInfo*
9889 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9890 {
9891         guint32 mtoken, i, len;
9892         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9893         MonoTableInfo *ca;
9894         MonoCustomAttrInfo *ainfo;
9895         GList *tmp, *list = NULL;
9896         const char *data;
9897         MonoCustomAttrEntry* attr;
9898
9899         mono_error_init (error);
9900
9901         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9902
9903         i = mono_metadata_custom_attrs_from_index (image, idx);
9904         if (!i)
9905                 return NULL;
9906         i --;
9907         while (i < ca->rows) {
9908                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9909                         break;
9910                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9911                 ++i;
9912         }
9913         len = g_list_length (list);
9914         if (!len)
9915                 return NULL;
9916         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9917         ainfo->num_attrs = len;
9918         ainfo->image = image;
9919         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9920                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9921                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9922                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9923                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9924                         mtoken |= MONO_TOKEN_METHOD_DEF;
9925                         break;
9926                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9927                         mtoken |= MONO_TOKEN_MEMBER_REF;
9928                         break;
9929                 default:
9930                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9931                         break;
9932                 }
9933                 attr = &ainfo->attrs [i - 1];
9934                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9935                 if (!attr->ctor) {
9936                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9937                         g_list_free (list);
9938                         g_free (ainfo);
9939                         return NULL;
9940                 }
9941
9942                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9943                         /*FIXME raising an exception here doesn't make any sense*/
9944                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9945                         g_list_free (list);
9946                         g_free (ainfo);
9947                         return NULL;
9948                 }
9949                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9950                 attr->data_size = mono_metadata_decode_value (data, &data);
9951                 attr->data = (guchar*)data;
9952         }
9953         g_list_free (list);
9954
9955         return ainfo;
9956 }
9957
9958 MonoCustomAttrInfo*
9959 mono_custom_attrs_from_method (MonoMethod *method)
9960 {
9961         MonoError error;
9962         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9963         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9964         return result;
9965 }
9966
9967 MonoCustomAttrInfo*
9968 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9969 {
9970         guint32 idx;
9971
9972         mono_error_init (error);
9973
9974         /*
9975          * An instantiated method has the same cattrs as the generic method definition.
9976          *
9977          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9978          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9979          */
9980         if (method->is_inflated)
9981                 method = ((MonoMethodInflated *) method)->declaring;
9982         
9983         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9984                 return lookup_custom_attr (method->klass->image, method);
9985
9986         if (!method->token)
9987                 /* Synthetic methods */
9988                 return NULL;
9989
9990         idx = mono_method_get_index (method);
9991         idx <<= MONO_CUSTOM_ATTR_BITS;
9992         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9993         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9994 }
9995
9996 MonoCustomAttrInfo*
9997 mono_custom_attrs_from_class (MonoClass *klass)
9998 {
9999         MonoError error;
10000         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
10001         mono_error_cleanup (&error);
10002         return result;
10003 }
10004
10005 MonoCustomAttrInfo*
10006 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
10007 {
10008         guint32 idx;
10009
10010         mono_error_init (error);
10011
10012         if (klass->generic_class)
10013                 klass = klass->generic_class->container_class;
10014
10015         if (image_is_dynamic (klass->image))
10016                 return lookup_custom_attr (klass->image, klass);
10017
10018         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
10019                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
10020                 idx <<= MONO_CUSTOM_ATTR_BITS;
10021                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
10022         } else {
10023                 idx = mono_metadata_token_index (klass->type_token);
10024                 idx <<= MONO_CUSTOM_ATTR_BITS;
10025                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10026         }
10027         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10028 }
10029
10030 MonoCustomAttrInfo*
10031 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10032 {
10033         MonoError error;
10034         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10035         mono_error_cleanup (&error);
10036         return result;
10037 }
10038
10039 MonoCustomAttrInfo*
10040 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10041 {
10042         guint32 idx;
10043         
10044         mono_error_init (error);
10045
10046         if (image_is_dynamic (assembly->image))
10047                 return lookup_custom_attr (assembly->image, assembly);
10048         idx = 1; /* there is only one assembly */
10049         idx <<= MONO_CUSTOM_ATTR_BITS;
10050         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10051         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10052 }
10053
10054 static MonoCustomAttrInfo*
10055 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10056 {
10057         guint32 idx;
10058         
10059         if (image_is_dynamic (image))
10060                 return lookup_custom_attr (image, image);
10061         idx = 1; /* there is only one module */
10062         idx <<= MONO_CUSTOM_ATTR_BITS;
10063         idx |= MONO_CUSTOM_ATTR_MODULE;
10064         return mono_custom_attrs_from_index_checked (image, idx, error);
10065 }
10066
10067 MonoCustomAttrInfo*
10068 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10069 {
10070         MonoError error;
10071         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10072         mono_error_cleanup (&error);
10073         return result;
10074 }
10075
10076 MonoCustomAttrInfo*
10077 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10078 {
10079         guint32 idx;
10080         
10081         if (image_is_dynamic (klass->image)) {
10082                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10083                 return lookup_custom_attr (klass->image, property);
10084         }
10085         idx = find_property_index (klass, property);
10086         idx <<= MONO_CUSTOM_ATTR_BITS;
10087         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10088         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10089 }
10090
10091 MonoCustomAttrInfo*
10092 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10093 {
10094         MonoError error;
10095         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10096         mono_error_cleanup (&error);
10097         return result;
10098 }
10099
10100 MonoCustomAttrInfo*
10101 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10102 {
10103         guint32 idx;
10104         
10105         if (image_is_dynamic (klass->image)) {
10106                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10107                 return lookup_custom_attr (klass->image, event);
10108         }
10109         idx = find_event_index (klass, event);
10110         idx <<= MONO_CUSTOM_ATTR_BITS;
10111         idx |= MONO_CUSTOM_ATTR_EVENT;
10112         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10113 }
10114
10115 MonoCustomAttrInfo*
10116 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10117 {
10118         MonoError error;
10119         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10120         mono_error_cleanup (&error);
10121         return result;
10122 }
10123
10124 MonoCustomAttrInfo*
10125 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10126 {
10127         guint32 idx;
10128         mono_error_init (error);
10129
10130         if (image_is_dynamic (klass->image)) {
10131                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10132                 return lookup_custom_attr (klass->image, field);
10133         }
10134         idx = find_field_index (klass, field);
10135         idx <<= MONO_CUSTOM_ATTR_BITS;
10136         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10137         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10138 }
10139
10140 /**
10141  * mono_custom_attrs_from_param:
10142  * @method: handle to the method that we want to retrieve custom parameter information from
10143  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10144  *
10145  * The result must be released with mono_custom_attrs_free().
10146  *
10147  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10148  */
10149 MonoCustomAttrInfo*
10150 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10151 {
10152         MonoError error;
10153         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10154         mono_error_cleanup (&error);
10155         return result;
10156 }
10157
10158 /**
10159  * mono_custom_attrs_from_param_checked:
10160  * @method: handle to the method that we want to retrieve custom parameter information from
10161  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10162  * @error: set on error
10163  *
10164  * The result must be released with mono_custom_attrs_free().
10165  *
10166  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10167  */
10168 MonoCustomAttrInfo*
10169 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10170 {
10171         MonoTableInfo *ca;
10172         guint32 i, idx, method_index;
10173         guint32 param_list, param_last, param_pos, found;
10174         MonoImage *image;
10175         MonoReflectionMethodAux *aux;
10176
10177         mono_error_init (error);
10178
10179         /*
10180          * An instantiated method has the same cattrs as the generic method definition.
10181          *
10182          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10183          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10184          */
10185         if (method->is_inflated)
10186                 method = ((MonoMethodInflated *) method)->declaring;
10187
10188         if (image_is_dynamic (method->klass->image)) {
10189                 MonoCustomAttrInfo *res, *ainfo;
10190                 int size;
10191
10192                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10193                 if (!aux || !aux->param_cattr)
10194                         return NULL;
10195
10196                 /* Need to copy since it will be freed later */
10197                 ainfo = aux->param_cattr [param];
10198                 if (!ainfo)
10199                         return NULL;
10200                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10201                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10202                 memcpy (res, ainfo, size);
10203                 return res;
10204         }
10205
10206         image = method->klass->image;
10207         method_index = mono_method_get_index (method);
10208         if (!method_index)
10209                 return NULL;
10210         ca = &image->tables [MONO_TABLE_METHOD];
10211
10212         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10213         if (method_index == ca->rows) {
10214                 ca = &image->tables [MONO_TABLE_PARAM];
10215                 param_last = ca->rows + 1;
10216         } else {
10217                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10218                 ca = &image->tables [MONO_TABLE_PARAM];
10219         }
10220         found = FALSE;
10221         for (i = param_list; i < param_last; ++i) {
10222                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10223                 if (param_pos == param) {
10224                         found = TRUE;
10225                         break;
10226                 }
10227         }
10228         if (!found)
10229                 return NULL;
10230         idx = i;
10231         idx <<= MONO_CUSTOM_ATTR_BITS;
10232         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10233         return mono_custom_attrs_from_index_checked (image, idx, error);
10234 }
10235
10236 gboolean
10237 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10238 {
10239         int i;
10240         MonoClass *klass;
10241         for (i = 0; i < ainfo->num_attrs; ++i) {
10242                 klass = ainfo->attrs [i].ctor->klass;
10243                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10244                         return TRUE;
10245         }
10246         return FALSE;
10247 }
10248
10249 MonoObject*
10250 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10251 {
10252         MonoError error;
10253         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10254         mono_error_assert_ok (&error); /*FIXME proper error handling*/
10255         return res;
10256 }
10257
10258 MonoObject*
10259 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10260 {
10261         int i, attr_index;
10262         MonoClass *klass;
10263         MonoArray *attrs;
10264
10265         mono_error_init (error);
10266
10267         attr_index = -1;
10268         for (i = 0; i < ainfo->num_attrs; ++i) {
10269                 klass = ainfo->attrs [i].ctor->klass;
10270                 if (mono_class_has_parent (klass, attr_klass)) {
10271                         attr_index = i;
10272                         break;
10273                 }
10274         }
10275         if (attr_index == -1)
10276                 return NULL;
10277
10278         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10279         if (!mono_error_ok (error))
10280                 return NULL;
10281         return mono_array_get (attrs, MonoObject*, attr_index);
10282 }
10283
10284 /*
10285  * mono_reflection_get_custom_attrs_info:
10286  * @obj: a reflection object handle
10287  *
10288  * Return the custom attribute info for attributes defined for the
10289  * reflection handle @obj. The objects.
10290  *
10291  * FIXME this function leaks like a sieve for SRE objects.
10292  */
10293 MonoCustomAttrInfo*
10294 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10295 {
10296         MonoError error;
10297         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10298         mono_error_assert_ok (&error);
10299         return result;
10300 }
10301
10302 /**
10303  * mono_reflection_get_custom_attrs_info_checked:
10304  * @obj: a reflection object handle
10305  * @error: set on error
10306  *
10307  * Return the custom attribute info for attributes defined for the
10308  * reflection handle @obj. The objects.
10309  *
10310  * On failure returns NULL and sets @error.
10311  *
10312  * FIXME this function leaks like a sieve for SRE objects.
10313  */
10314 MonoCustomAttrInfo*
10315 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10316 {
10317         MonoClass *klass;
10318         MonoCustomAttrInfo *cinfo = NULL;
10319         
10320         mono_error_init (error);
10321
10322         klass = obj->vtable->klass;
10323         if (klass == mono_defaults.monotype_class) {
10324                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10325                 return_val_if_nok (error, NULL);
10326                 klass = mono_class_from_mono_type (type);
10327                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10328                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10329                 return_val_if_nok (error, NULL);
10330         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10331                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10332                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10333                 return_val_if_nok (error, NULL);
10334         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10335                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10336                 cinfo = mono_custom_attrs_from_module (module->image, error);
10337                 return_val_if_nok (error, NULL);
10338         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10339                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10340                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10341                 return_val_if_nok (error, NULL);
10342         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10343                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10344                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10345                 return_val_if_nok (error, NULL);
10346         } else if (strcmp ("MonoField", klass->name) == 0) {
10347                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10348                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10349                 return_val_if_nok (error, NULL);
10350         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10351                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10352                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10353                 return_val_if_nok (error, NULL);
10354         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10355                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10356                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10357                 return_val_if_nok (error, NULL);
10358         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10359                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10360                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10361                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10362                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10363                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10364                         return_val_if_nok (error, NULL);
10365                 } else if (is_sr_mono_property (member_class)) {
10366                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10367                         MonoMethod *method;
10368                         if (!(method = prop->property->get))
10369                                 method = prop->property->set;
10370                         g_assert (method);
10371
10372                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10373                         return_val_if_nok (error, NULL);
10374                 } 
10375 #ifndef DISABLE_REFLECTION_EMIT
10376                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10377                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10378                         return_val_if_nok (error, NULL);
10379                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10380                         return_val_if_nok (error, NULL);
10381                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10382                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10383                         MonoMethod *method = NULL;
10384                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10385                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10386                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10387                                 method = ((MonoReflectionMethod *)c->cb)->method;
10388                         else
10389                                 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));
10390
10391                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10392                         return_val_if_nok (error, NULL);
10393                 } 
10394 #endif
10395                 else {
10396                         char *type_name = mono_type_get_full_name (member_class);
10397                         mono_error_set_not_supported (error,
10398                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10399                                                       type_name);
10400                         g_free (type_name);
10401                         return NULL;
10402                 }
10403         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10404                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10405                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10406         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10407                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10408                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10409         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10410                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10411                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10412         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10413                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10414                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10415         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10416                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10417                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10418         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10419                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10420                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10421         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10422                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10423                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10424                 return_val_if_nok (error, NULL);
10425         } else { /* handle other types here... */
10426                 g_error ("get custom attrs not yet supported for %s", klass->name);
10427         }
10428
10429         return cinfo;
10430 }
10431
10432 /*
10433  * mono_reflection_get_custom_attrs_by_type:
10434  * @obj: a reflection object handle
10435  *
10436  * Return an array with all the custom attributes defined of the
10437  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10438  * of that type are returned. The objects are fully build. Return NULL if a loading error
10439  * occurs.
10440  */
10441 MonoArray*
10442 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10443 {
10444         MonoArray *result;
10445         MonoCustomAttrInfo *cinfo;
10446
10447         mono_error_init (error);
10448
10449         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10450         return_val_if_nok (error, NULL);
10451         if (cinfo) {
10452                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10453                 if (!cinfo->cached)
10454                         mono_custom_attrs_free (cinfo);
10455                 if (!result)
10456                         return NULL;
10457         } else {
10458                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10459         }
10460
10461         return result;
10462 }
10463
10464 /*
10465  * mono_reflection_get_custom_attrs:
10466  * @obj: a reflection object handle
10467  *
10468  * Return an array with all the custom attributes defined of the
10469  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10470  * occurs.
10471  */
10472 MonoArray*
10473 mono_reflection_get_custom_attrs (MonoObject *obj)
10474 {
10475         MonoError error;
10476
10477         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10478 }
10479
10480 /*
10481  * mono_reflection_get_custom_attrs_data:
10482  * @obj: a reflection obj handle
10483  *
10484  * Returns an array of System.Reflection.CustomAttributeData,
10485  * which include information about attributes reflected on
10486  * types loaded using the Reflection Only methods
10487  */
10488 MonoArray*
10489 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10490 {
10491         MonoError error;
10492         MonoArray* result;
10493         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10494         mono_error_cleanup (&error);
10495         return result;
10496 }
10497
10498 /*
10499  * mono_reflection_get_custom_attrs_data_checked:
10500  * @obj: a reflection obj handle
10501  * @error: set on error
10502  *
10503  * Returns an array of System.Reflection.CustomAttributeData,
10504  * which include information about attributes reflected on
10505  * types loaded using the Reflection Only methods
10506  */
10507 MonoArray*
10508 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10509 {
10510         MonoArray *result;
10511         MonoCustomAttrInfo *cinfo;
10512
10513         mono_error_init (error);
10514
10515         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10516         return_val_if_nok (error, NULL);
10517         if (cinfo) {
10518                 result = mono_custom_attrs_data_construct (cinfo, error);
10519                 if (!cinfo->cached)
10520                         mono_custom_attrs_free (cinfo);
10521                 return_val_if_nok (error, NULL);
10522         } else
10523                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10524
10525         return result;
10526 }
10527
10528 static MonoReflectionType*
10529 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10530 {
10531         static MonoMethod *method_get_underlying_system_type = NULL;
10532         MonoReflectionType *rt;
10533         MonoMethod *usertype_method;
10534
10535         mono_error_init (error);
10536
10537         if (!method_get_underlying_system_type)
10538                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10539
10540         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10541
10542         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10543
10544         return rt;
10545 }
10546
10547
10548 static gboolean
10549 is_corlib_type (MonoClass *klass)
10550 {
10551         return klass->image == mono_defaults.corlib;
10552 }
10553
10554 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10555         static MonoClass *cached_class; \
10556         if (cached_class) \
10557                 return cached_class == _class; \
10558         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10559                 cached_class = _class; \
10560                 return TRUE; \
10561         } \
10562         return FALSE; \
10563 } while (0) \
10564
10565
10566 #ifndef DISABLE_REFLECTION_EMIT
10567 static gboolean
10568 is_sre_array (MonoClass *klass)
10569 {
10570         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10571 }
10572
10573 static gboolean
10574 is_sre_byref (MonoClass *klass)
10575 {
10576         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10577 }
10578
10579 static gboolean
10580 is_sre_pointer (MonoClass *klass)
10581 {
10582         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10583 }
10584
10585 static gboolean
10586 is_sre_generic_instance (MonoClass *klass)
10587 {
10588         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10589 }
10590
10591 static gboolean
10592 is_sre_type_builder (MonoClass *klass)
10593 {
10594         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10595 }
10596
10597 static gboolean
10598 is_sre_method_builder (MonoClass *klass)
10599 {
10600         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10601 }
10602
10603 static gboolean
10604 is_sre_ctor_builder (MonoClass *klass)
10605 {
10606         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10607 }
10608
10609 static gboolean
10610 is_sre_field_builder (MonoClass *klass)
10611 {
10612         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10613 }
10614
10615 static gboolean
10616 is_sre_method_on_tb_inst (MonoClass *klass)
10617 {
10618         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10619 }
10620
10621 static gboolean
10622 is_sre_ctor_on_tb_inst (MonoClass *klass)
10623 {
10624         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10625 }
10626
10627 MonoType*
10628 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10629 {
10630         MonoClass *klass;
10631         mono_error_init (error);
10632
10633         if (!ref)
10634                 return NULL;
10635         if (ref->type)
10636                 return ref->type;
10637
10638         if (is_usertype (ref)) {
10639                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10640                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10641                         return NULL;
10642                 if (ref->type)
10643                         return ref->type;
10644         }
10645
10646         klass = mono_object_class (ref);
10647
10648         if (is_sre_array (klass)) {
10649                 MonoType *res;
10650                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10651                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10652                 return_val_if_nok (error, NULL);
10653                 g_assert (base);
10654                 if (sre_array->rank == 0) //single dimentional array
10655                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10656                 else
10657                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10658                 sre_array->type.type = res;
10659                 return res;
10660         } else if (is_sre_byref (klass)) {
10661                 MonoType *res;
10662                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10663                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10664                 return_val_if_nok (error, NULL);
10665                 g_assert (base);
10666                 res = &mono_class_from_mono_type (base)->this_arg;
10667                 sre_byref->type.type = res;
10668                 return res;
10669         } else if (is_sre_pointer (klass)) {
10670                 MonoType *res;
10671                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10672                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10673                 return_val_if_nok (error, NULL);
10674                 g_assert (base);
10675                 res = &mono_ptr_class_get (base)->byval_arg;
10676                 sre_pointer->type.type = res;
10677                 return res;
10678         } else if (is_sre_generic_instance (klass)) {
10679                 MonoType *res, **types;
10680                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10681                 int i, count;
10682
10683                 count = mono_array_length (gclass->type_arguments);
10684                 types = g_new0 (MonoType*, count);
10685                 for (i = 0; i < count; ++i) {
10686                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10687                         types [i] = mono_reflection_type_get_handle (t, error);
10688                         if (!types[i] || !is_ok (error)) {
10689                                 g_free (types);
10690                                 return NULL;
10691                         }
10692                 }
10693
10694                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10695                 g_free (types);
10696                 g_assert (res);
10697                 gclass->type.type = res;
10698                 return res;
10699         }
10700
10701         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10702         return NULL;
10703 }
10704
10705 void
10706 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10707 {
10708         MonoError error;
10709         mono_reflection_type_get_handle (type, &error);
10710         mono_error_set_pending_exception (&error);
10711 }
10712
10713 static gboolean
10714 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10715 {
10716         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10717         MonoClass *klass;
10718
10719         mono_error_init (error);
10720
10721         MonoType *res = mono_reflection_type_get_handle (type, error);
10722
10723         if (!res && is_ok (error)) {
10724                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10725         }
10726         return_val_if_nok (error, FALSE);
10727
10728         klass = mono_class_from_mono_type (res);
10729
10730         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10731         mono_domain_lock (domain);
10732
10733         if (!image_is_dynamic (klass->image)) {
10734                 mono_class_setup_supertypes (klass);
10735         } else {
10736                 if (!domain->type_hash)
10737                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10738                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10739                 mono_g_hash_table_insert (domain->type_hash, res, type);
10740         }
10741         mono_domain_unlock (domain);
10742         mono_loader_unlock ();
10743
10744         return TRUE;
10745 }
10746
10747 void
10748 mono_reflection_register_with_runtime (MonoReflectionType *type)
10749 {
10750         MonoError error;
10751         (void) reflection_register_with_runtime (type, &error);
10752         mono_error_set_pending_exception (&error);
10753 }
10754
10755 /**
10756  * LOCKING: Assumes the loader lock is held.
10757  */
10758 static MonoMethodSignature*
10759 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10760         MonoMethodSignature *sig;
10761         int count, i;
10762
10763         mono_error_init (error);
10764
10765         count = parameters? mono_array_length (parameters): 0;
10766
10767         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10768         sig->param_count = count;
10769         sig->sentinelpos = -1; /* FIXME */
10770         for (i = 0; i < count; ++i) {
10771                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10772                 if (!is_ok (error)) {
10773                         image_g_free (image, sig);
10774                         return NULL;
10775                 }
10776         }
10777         return sig;
10778 }
10779
10780 /**
10781  * LOCKING: Assumes the loader lock is held.
10782  */
10783 static MonoMethodSignature*
10784 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10785         MonoMethodSignature *sig;
10786
10787         mono_error_init (error);
10788
10789         sig = parameters_to_signature (image, ctor->parameters, error);
10790         return_val_if_nok (error, NULL);
10791         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10792         sig->ret = &mono_defaults.void_class->byval_arg;
10793         return sig;
10794 }
10795
10796 /**
10797  * LOCKING: Assumes the loader lock is held.
10798  */
10799 static MonoMethodSignature*
10800 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10801         MonoMethodSignature *sig;
10802
10803         mono_error_init (error);
10804
10805         sig = parameters_to_signature (image, method->parameters, error);
10806         return_val_if_nok (error, NULL);
10807         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10808         if (method->rtype) {
10809                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10810                 if (!is_ok (error)) {
10811                         image_g_free (image, sig);
10812                         return NULL;
10813                 }
10814         } else {
10815                 sig->ret = &mono_defaults.void_class->byval_arg;
10816         }
10817         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10818         return sig;
10819 }
10820
10821 static MonoMethodSignature*
10822 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10823         MonoMethodSignature *sig;
10824
10825         mono_error_init (error);
10826
10827         sig = parameters_to_signature (NULL, method->parameters, error);
10828         return_val_if_nok (error, NULL);
10829         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10830         if (method->rtype) {
10831                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10832                 if (!is_ok (error)) {
10833                         g_free (sig);
10834                         return NULL;
10835                 }
10836         } else {
10837                 sig->ret = &mono_defaults.void_class->byval_arg;
10838         }
10839         sig->generic_param_count = 0;
10840         return sig;
10841 }
10842
10843 static void
10844 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10845 {
10846         mono_error_init (error);
10847         MonoClass *klass = mono_object_class (prop);
10848         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10849                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10850                 *name = mono_string_to_utf8 (pb->name);
10851                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10852         } else {
10853                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10854                 *name = g_strdup (p->property->name);
10855                 if (p->property->get)
10856                         *type = mono_method_signature (p->property->get)->ret;
10857                 else
10858                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10859         }
10860 }
10861
10862 static void
10863 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10864 {
10865         mono_error_init (error);
10866         MonoClass *klass = mono_object_class (field);
10867         if (strcmp (klass->name, "FieldBuilder") == 0) {
10868                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10869                 *name = mono_string_to_utf8 (fb->name);
10870                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10871         } else {
10872                 MonoReflectionField *f = (MonoReflectionField *)field;
10873                 *name = g_strdup (mono_field_get_name (f->field));
10874                 *type = f->field->type;
10875         }
10876 }
10877
10878 #else /* DISABLE_REFLECTION_EMIT */
10879
10880 void
10881 mono_reflection_register_with_runtime (MonoReflectionType *type)
10882 {
10883         /* This is empty */
10884 }
10885
10886 static gboolean
10887 is_sre_type_builder (MonoClass *klass)
10888 {
10889         return FALSE;
10890 }
10891
10892 static gboolean
10893 is_sre_generic_instance (MonoClass *klass)
10894 {
10895         return FALSE;
10896 }
10897
10898 static void
10899 init_type_builder_generics (MonoObject *type, MonoError *error)
10900 {
10901         mono_error_init (error);
10902 }
10903
10904 #endif /* !DISABLE_REFLECTION_EMIT */
10905
10906
10907 static gboolean
10908 is_sr_mono_field (MonoClass *klass)
10909 {
10910         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10911 }
10912
10913 static gboolean
10914 is_sr_mono_property (MonoClass *klass)
10915 {
10916         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10917 }
10918
10919 static gboolean
10920 is_sr_mono_method (MonoClass *klass)
10921 {
10922         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10923 }
10924
10925 static gboolean
10926 is_sr_mono_cmethod (MonoClass *klass)
10927 {
10928         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10929 }
10930
10931 static gboolean
10932 is_sr_mono_generic_method (MonoClass *klass)
10933 {
10934         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10935 }
10936
10937 static gboolean
10938 is_sr_mono_generic_cmethod (MonoClass *klass)
10939 {
10940         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10941 }
10942
10943 gboolean
10944 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10945 {
10946         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10947 }
10948
10949 static gboolean
10950 is_usertype (MonoReflectionType *ref)
10951 {
10952         MonoClass *klass = mono_object_class (ref);
10953         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10954 }
10955
10956 static MonoReflectionType*
10957 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10958 {
10959         mono_error_init (error);
10960         if (!type || type->type)
10961                 return type;
10962
10963         if (is_usertype (type)) {
10964                 type = mono_reflection_type_get_underlying_system_type (type, error);
10965                 return_val_if_nok (error, NULL);
10966                 if (is_usertype (type)) {
10967                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10968                         return NULL;
10969                 }
10970         }
10971
10972         return type;
10973 }
10974 /**
10975  * encode_cattr_value:
10976  * Encode a value in a custom attribute stream of bytes.
10977  * The value to encode is either supplied as an object in argument val
10978  * (valuetypes are boxed), or as a pointer to the data in the
10979  * argument argval.
10980  * @type represents the type of the value
10981  * @buffer is the start of the buffer
10982  * @p the current position in the buffer
10983  * @buflen contains the size of the buffer and is used to return the new buffer size
10984  * if this needs to be realloced.
10985  * @retbuffer and @retp return the start and the position of the buffer
10986  * @error set on error.
10987  */
10988 static void
10989 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10990 {
10991         MonoTypeEnum simple_type;
10992         
10993         mono_error_init (error);
10994         if ((p-buffer) + 10 >= *buflen) {
10995                 char *newbuf;
10996                 *buflen *= 2;
10997                 newbuf = (char *)g_realloc (buffer, *buflen);
10998                 p = newbuf + (p-buffer);
10999                 buffer = newbuf;
11000         }
11001         if (!argval)
11002                 argval = ((char*)arg + sizeof (MonoObject));
11003         simple_type = type->type;
11004 handle_enum:
11005         switch (simple_type) {
11006         case MONO_TYPE_BOOLEAN:
11007         case MONO_TYPE_U1:
11008         case MONO_TYPE_I1:
11009                 *p++ = *argval;
11010                 break;
11011         case MONO_TYPE_CHAR:
11012         case MONO_TYPE_U2:
11013         case MONO_TYPE_I2:
11014                 swap_with_size (p, argval, 2, 1);
11015                 p += 2;
11016                 break;
11017         case MONO_TYPE_U4:
11018         case MONO_TYPE_I4:
11019         case MONO_TYPE_R4:
11020                 swap_with_size (p, argval, 4, 1);
11021                 p += 4;
11022                 break;
11023         case MONO_TYPE_R8:
11024                 swap_with_size (p, argval, 8, 1);
11025                 p += 8;
11026                 break;
11027         case MONO_TYPE_U8:
11028         case MONO_TYPE_I8:
11029                 swap_with_size (p, argval, 8, 1);
11030                 p += 8;
11031                 break;
11032         case MONO_TYPE_VALUETYPE:
11033                 if (type->data.klass->enumtype) {
11034                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11035                         goto handle_enum;
11036                 } else {
11037                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11038                 }
11039                 break;
11040         case MONO_TYPE_STRING: {
11041                 char *str;
11042                 guint32 slen;
11043                 if (!arg) {
11044                         *p++ = 0xFF;
11045                         break;
11046                 }
11047                 str = mono_string_to_utf8 ((MonoString*)arg);
11048                 slen = strlen (str);
11049                 if ((p-buffer) + 10 + slen >= *buflen) {
11050                         char *newbuf;
11051                         *buflen *= 2;
11052                         *buflen += slen;
11053                         newbuf = (char *)g_realloc (buffer, *buflen);
11054                         p = newbuf + (p-buffer);
11055                         buffer = newbuf;
11056                 }
11057                 mono_metadata_encode_value (slen, p, &p);
11058                 memcpy (p, str, slen);
11059                 p += slen;
11060                 g_free (str);
11061                 break;
11062         }
11063         case MONO_TYPE_CLASS: {
11064                 char *str;
11065                 guint32 slen;
11066                 MonoType *arg_type;
11067                 if (!arg) {
11068                         *p++ = 0xFF;
11069                         break;
11070                 }
11071 handle_type:
11072                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11073                 return_if_nok (error);
11074
11075                 str = type_get_qualified_name (arg_type, NULL);
11076                 slen = strlen (str);
11077                 if ((p-buffer) + 10 + slen >= *buflen) {
11078                         char *newbuf;
11079                         *buflen *= 2;
11080                         *buflen += slen;
11081                         newbuf = (char *)g_realloc (buffer, *buflen);
11082                         p = newbuf + (p-buffer);
11083                         buffer = newbuf;
11084                 }
11085                 mono_metadata_encode_value (slen, p, &p);
11086                 memcpy (p, str, slen);
11087                 p += slen;
11088                 g_free (str);
11089                 break;
11090         }
11091         case MONO_TYPE_SZARRAY: {
11092                 int len, i;
11093                 MonoClass *eclass, *arg_eclass;
11094
11095                 if (!arg) {
11096                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11097                         break;
11098                 }
11099                 len = mono_array_length ((MonoArray*)arg);
11100                 *p++ = len & 0xff;
11101                 *p++ = (len >> 8) & 0xff;
11102                 *p++ = (len >> 16) & 0xff;
11103                 *p++ = (len >> 24) & 0xff;
11104                 *retp = p;
11105                 *retbuffer = buffer;
11106                 eclass = type->data.klass;
11107                 arg_eclass = mono_object_class (arg)->element_class;
11108
11109                 if (!eclass) {
11110                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11111                         eclass = mono_defaults.object_class;
11112                 }
11113                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11114                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11115                         int elsize = mono_class_array_element_size (arg_eclass);
11116                         for (i = 0; i < len; ++i) {
11117                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11118                                 return_if_nok (error);
11119                                 elptr += elsize;
11120                         }
11121                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11122                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11123                         int elsize = mono_class_array_element_size (eclass);
11124                         for (i = 0; i < len; ++i) {
11125                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11126                                 return_if_nok (error);
11127                                 elptr += elsize;
11128                         }
11129                 } else {
11130                         for (i = 0; i < len; ++i) {
11131                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11132                                 return_if_nok (error);
11133                         }
11134                 }
11135                 break;
11136         }
11137         case MONO_TYPE_OBJECT: {
11138                 MonoClass *klass;
11139                 char *str;
11140                 guint32 slen;
11141
11142                 /*
11143                  * The parameter type is 'object' but the type of the actual
11144                  * argument is not. So we have to add type information to the blob
11145                  * too. This is completely undocumented in the spec.
11146                  */
11147
11148                 if (arg == NULL) {
11149                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11150                         *p++ = 0xFF;
11151                         break;
11152                 }
11153                 
11154                 klass = mono_object_class (arg);
11155
11156                 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
11157                         *p++ = 0x50;
11158                         goto handle_type;
11159                 } else {
11160                         return_if_nok (error);
11161                 }
11162
11163                 if (klass->enumtype) {
11164                         *p++ = 0x55;
11165                 } else if (klass == mono_defaults.string_class) {
11166                         simple_type = MONO_TYPE_STRING;
11167                         *p++ = 0x0E;
11168                         goto handle_enum;
11169                 } else if (klass->rank == 1) {
11170                         *p++ = 0x1D;
11171                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11172                                 /* See Partition II, Appendix B3 */
11173                                 *p++ = 0x51;
11174                         else
11175                                 *p++ = klass->element_class->byval_arg.type;
11176                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11177                         return_if_nok (error);
11178                         break;
11179                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11180                         *p++ = simple_type = klass->byval_arg.type;
11181                         goto handle_enum;
11182                 } else {
11183                         g_error ("unhandled type in custom attr");
11184                 }
11185                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11186                 slen = strlen (str);
11187                 if ((p-buffer) + 10 + slen >= *buflen) {
11188                         char *newbuf;
11189                         *buflen *= 2;
11190                         *buflen += slen;
11191                         newbuf = (char *)g_realloc (buffer, *buflen);
11192                         p = newbuf + (p-buffer);
11193                         buffer = newbuf;
11194                 }
11195                 mono_metadata_encode_value (slen, p, &p);
11196                 memcpy (p, str, slen);
11197                 p += slen;
11198                 g_free (str);
11199                 simple_type = mono_class_enum_basetype (klass)->type;
11200                 goto handle_enum;
11201         }
11202         default:
11203                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11204         }
11205         *retp = p;
11206         *retbuffer = buffer;
11207 }
11208
11209 static void
11210 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11211 {
11212         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11213                 char *str = type_get_qualified_name (type, NULL);
11214                 int slen = strlen (str);
11215
11216                 *p++ = 0x55;
11217                 /*
11218                  * This seems to be optional...
11219                  * *p++ = 0x80;
11220                  */
11221                 mono_metadata_encode_value (slen, p, &p);
11222                 memcpy (p, str, slen);
11223                 p += slen;
11224                 g_free (str);
11225         } else if (type->type == MONO_TYPE_OBJECT) {
11226                 *p++ = 0x51;
11227         } else if (type->type == MONO_TYPE_CLASS) {
11228                 /* it should be a type: encode_cattr_value () has the check */
11229                 *p++ = 0x50;
11230         } else {
11231                 mono_metadata_encode_value (type->type, p, &p);
11232                 if (type->type == MONO_TYPE_SZARRAY)
11233                         /* See the examples in Partition VI, Annex B */
11234                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11235         }
11236
11237         *retp = p;
11238 }
11239
11240 #ifndef DISABLE_REFLECTION_EMIT
11241 static void
11242 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11243 {
11244         int len;
11245
11246         mono_error_init (error);
11247
11248         /* Preallocate a large enough buffer */
11249         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11250                 char *str = type_get_qualified_name (type, NULL);
11251                 len = strlen (str);
11252                 g_free (str);
11253         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11254                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11255                 len = strlen (str);
11256                 g_free (str);
11257         } else {
11258                 len = 0;
11259         }
11260         len += strlen (name);
11261
11262         if ((p-buffer) + 20 + len >= *buflen) {
11263                 char *newbuf;
11264                 *buflen *= 2;
11265                 *buflen += len;
11266                 newbuf = (char *)g_realloc (buffer, *buflen);
11267                 p = newbuf + (p-buffer);
11268                 buffer = newbuf;
11269         }
11270
11271         encode_field_or_prop_type (type, p, &p);
11272
11273         len = strlen (name);
11274         mono_metadata_encode_value (len, p, &p);
11275         memcpy (p, name, len);
11276         p += len;
11277         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11278         return_if_nok (error);
11279         *retp = p;
11280         *retbuffer = buffer;
11281 }
11282
11283 /**
11284  * mono_reflection_get_custom_attrs_blob:
11285  * @ctor: custom attribute constructor
11286  * @ctorArgs: arguments o the constructor
11287  * @properties:
11288  * @propValues:
11289  * @fields:
11290  * @fieldValues:
11291  * 
11292  * Creates the blob of data that needs to be saved in the metadata and that represents
11293  * the custom attributed described by @ctor, @ctorArgs etc.
11294  * Returns: a Byte array representing the blob of data.
11295  */
11296 MonoArray*
11297 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11298 {
11299         MonoError error;
11300         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11301         mono_error_cleanup (&error);
11302         return result;
11303 }
11304
11305 /**
11306  * mono_reflection_get_custom_attrs_blob_checked:
11307  * @ctor: custom attribute constructor
11308  * @ctorArgs: arguments o the constructor
11309  * @properties:
11310  * @propValues:
11311  * @fields:
11312  * @fieldValues:
11313  * @error: set on error
11314  * 
11315  * Creates the blob of data that needs to be saved in the metadata and that represents
11316  * the custom attributed described by @ctor, @ctorArgs etc.
11317  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11318  */
11319 MonoArray*
11320 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11321 {
11322         MonoArray *result = NULL;
11323         MonoMethodSignature *sig;
11324         MonoObject *arg;
11325         char *buffer, *p;
11326         guint32 buflen, i;
11327
11328         mono_error_init (error);
11329
11330         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11331                 /* sig is freed later so allocate it in the heap */
11332                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11333                 if (!is_ok (error)) {
11334                         g_free (sig);
11335                         return NULL;
11336                 }
11337         } else {
11338                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11339         }
11340
11341         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11342         buflen = 256;
11343         p = buffer = (char *)g_malloc (buflen);
11344         /* write the prolog */
11345         *p++ = 1;
11346         *p++ = 0;
11347         for (i = 0; i < sig->param_count; ++i) {
11348                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11349                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11350                 if (!is_ok (error)) goto leave;
11351         }
11352         i = 0;
11353         if (properties)
11354                 i += mono_array_length (properties);
11355         if (fields)
11356                 i += mono_array_length (fields);
11357         *p++ = i & 0xff;
11358         *p++ = (i >> 8) & 0xff;
11359         if (properties) {
11360                 MonoObject *prop;
11361                 for (i = 0; i < mono_array_length (properties); ++i) {
11362                         MonoType *ptype;
11363                         char *pname;
11364
11365                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11366                         get_prop_name_and_type (prop, &pname, &ptype, error);
11367                         if (!is_ok (error)) goto leave;
11368                         *p++ = 0x54; /* PROPERTY signature */
11369                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11370                         g_free (pname);
11371                         if (!is_ok (error)) goto leave;
11372                 }
11373         }
11374
11375         if (fields) {
11376                 MonoObject *field;
11377                 for (i = 0; i < mono_array_length (fields); ++i) {
11378                         MonoType *ftype;
11379                         char *fname;
11380
11381                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11382                         get_field_name_and_type (field, &fname, &ftype, error);
11383                         if (!is_ok (error)) goto leave;
11384                         *p++ = 0x53; /* FIELD signature */
11385                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11386                         g_free (fname);
11387                         if (!is_ok (error)) goto leave;
11388                 }
11389         }
11390
11391         g_assert (p - buffer <= buflen);
11392         buflen = p - buffer;
11393         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11394         p = mono_array_addr (result, char, 0);
11395         memcpy (p, buffer, buflen);
11396 leave:
11397         g_free (buffer);
11398         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11399                 g_free (sig);
11400         return result;
11401 }
11402
11403 /**
11404  * reflection_setup_internal_class:
11405  * @tb: a TypeBuilder object
11406  * @error: set on error
11407  *
11408  * Creates a MonoClass that represents the TypeBuilder.
11409  * This is a trick that lets us simplify a lot of reflection code
11410  * (and will allow us to support Build and Run assemblies easier).
11411  *
11412  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11413  */
11414 static gboolean
11415 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11416 {
11417         MonoClass *klass, *parent;
11418
11419         mono_error_init (error);
11420         RESOLVE_TYPE (tb->parent, error);
11421         return_val_if_nok (error, FALSE);
11422
11423         mono_loader_lock ();
11424
11425         if (tb->parent) {
11426                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11427                 if (!is_ok (error)) {
11428                         mono_loader_unlock ();
11429                         return FALSE;
11430                 }
11431                 /* check so we can compile corlib correctly */
11432                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11433                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11434                         parent = parent_type->data.klass;
11435                 } else {
11436                         parent = mono_class_from_mono_type (parent_type);
11437                 }
11438         } else {
11439                 parent = NULL;
11440         }
11441         
11442         /* the type has already being created: it means we just have to change the parent */
11443         if (tb->type.type) {
11444                 klass = mono_class_from_mono_type (tb->type.type);
11445                 klass->parent = NULL;
11446                 /* fool mono_class_setup_parent */
11447                 klass->supertypes = NULL;
11448                 mono_class_setup_parent (klass, parent);
11449                 mono_class_setup_mono_type (klass);
11450                 mono_loader_unlock ();
11451                 return TRUE;
11452         }
11453
11454         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11455
11456         klass->image = &tb->module->dynamic_image->image;
11457
11458         klass->inited = 1; /* we lie to the runtime */
11459         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11460         if (!is_ok (error))
11461                 goto failure;
11462         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11463         if (!is_ok (error))
11464                 goto failure;
11465         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11466         klass->flags = tb->attrs;
11467         
11468         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11469
11470         klass->element_class = klass;
11471
11472         if (mono_class_get_ref_info (klass) == NULL) {
11473
11474                 mono_class_set_ref_info (klass, tb);
11475
11476                 /* Put into cache so mono_class_get_checked () will find it.
11477                 Skip nested types as those should not be available on the global scope. */
11478                 if (!tb->nesting_type)
11479                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11480
11481                 /*
11482                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11483                 by performing a mono_class_get which does the full resolution.
11484
11485                 Working around this semantics would require us to write a lot of code for no clear advantage.
11486                 */
11487                 mono_image_append_class_to_reflection_info_set (klass);
11488         } else {
11489                 g_assert (mono_class_get_ref_info (klass) == tb);
11490         }
11491
11492         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11493
11494         if (parent != NULL) {
11495                 mono_class_setup_parent (klass, parent);
11496         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11497                 const char *old_n = klass->name;
11498                 /* trick to get relative numbering right when compiling corlib */
11499                 klass->name = "BuildingObject";
11500                 mono_class_setup_parent (klass, mono_defaults.object_class);
11501                 klass->name = old_n;
11502         }
11503
11504         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11505                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11506                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11507                 klass->instance_size = sizeof (MonoObject);
11508                 klass->size_inited = 1;
11509                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11510         }
11511
11512         mono_class_setup_mono_type (klass);
11513
11514         mono_class_setup_supertypes (klass);
11515
11516         /*
11517          * FIXME: handle interfaces.
11518          */
11519
11520         tb->type.type = &klass->byval_arg;
11521
11522         if (tb->nesting_type) {
11523                 g_assert (tb->nesting_type->type);
11524                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11525                 if (!is_ok (error)) goto failure;
11526                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11527         }
11528
11529         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11530
11531         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11532         
11533         mono_loader_unlock ();
11534         return TRUE;
11535
11536 failure:
11537         mono_loader_unlock ();
11538         return FALSE;
11539 }
11540
11541 /**
11542  * mono_reflection_setup_internal_class:
11543  * @tb: a TypeBuilder object
11544  *
11545  * (icall)
11546  * Creates a MonoClass that represents the TypeBuilder.
11547  * This is a trick that lets us simplify a lot of reflection code
11548  * (and will allow us to support Build and Run assemblies easier).
11549  *
11550  */
11551 void
11552 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11553 {
11554         MonoError error;
11555         (void) reflection_setup_internal_class (tb, &error);
11556         mono_error_set_pending_exception (&error);
11557 }
11558
11559 /*
11560  * mono_reflection_setup_generic_class:
11561  * @tb: a TypeBuilder object
11562  *
11563  * Setup the generic class before adding the first generic parameter.
11564  */
11565 void
11566 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11567 {
11568 }
11569
11570 /**
11571  * mono_reflection_create_generic_class:
11572  * @tb: a TypeBuilder object
11573  * @error: set on error
11574  *
11575  * Creates the generic class after all generic parameters have been added.
11576  * On success returns TRUE, on failure returns FALSE and sets @error.
11577  * 
11578  */
11579 gboolean
11580 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11581 {
11582
11583         MonoClass *klass;
11584         int count, i;
11585
11586         mono_error_init (error);
11587
11588         klass = mono_class_from_mono_type (tb->type.type);
11589
11590         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11591
11592         if (klass->generic_container || (count == 0))
11593                 return TRUE;
11594
11595         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11596
11597         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11598
11599         klass->generic_container->owner.klass = klass;
11600         klass->generic_container->type_argc = count;
11601         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11602
11603         klass->is_generic = 1;
11604
11605         for (i = 0; i < count; i++) {
11606                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11607                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
11608                 return_val_if_nok (error, FALSE);
11609                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11610                 klass->generic_container->type_params [i] = *param;
11611                 /*Make sure we are a diferent type instance */
11612                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11613                 klass->generic_container->type_params [i].info.pklass = NULL;
11614                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11615
11616                 g_assert (klass->generic_container->type_params [i].param.owner);
11617         }
11618
11619         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11620         return TRUE;
11621 }
11622
11623 /**
11624  * reflection_create_internal_class:
11625  * @tb: a TypeBuilder object
11626  * @error: set on error
11627  *
11628  * Actually create the MonoClass that is associated with the TypeBuilder.
11629  * On success returns TRUE, on failure returns FALSE and sets @error.
11630  *
11631  */
11632 static gboolean
11633 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11634 {
11635
11636         MonoClass *klass;
11637
11638         mono_error_init (error);
11639         klass = mono_class_from_mono_type (tb->type.type);
11640
11641         mono_loader_lock ();
11642         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11643                 MonoReflectionFieldBuilder *fb;
11644                 MonoClass *ec;
11645                 MonoType *enum_basetype;
11646
11647                 g_assert (tb->fields != NULL);
11648                 g_assert (mono_array_length (tb->fields) >= 1);
11649
11650                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11651
11652                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11653                 if (!is_ok (error)) {
11654                         mono_loader_unlock ();
11655                         return FALSE;
11656                 }
11657                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11658                         mono_loader_unlock ();
11659                         return TRUE;
11660                 }
11661
11662                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11663                 if (!is_ok (error)) {
11664                         mono_loader_unlock ();
11665                         return FALSE;
11666                 }
11667                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11668                 if (!klass->element_class)
11669                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11670
11671                 /*
11672                  * get the element_class from the current corlib.
11673                  */
11674                 ec = default_class_from_mono_type (enum_basetype);
11675                 klass->instance_size = ec->instance_size;
11676                 klass->size_inited = 1;
11677                 /* 
11678                  * this is almost safe to do with enums and it's needed to be able
11679                  * to create objects of the enum type (for use in SetConstant).
11680                  */
11681                 /* FIXME: Does this mean enums can't have method overrides ? */
11682                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11683         }
11684         mono_loader_unlock ();
11685         return TRUE;
11686 }
11687
11688 /**
11689  * mono_reflection_create_internal_class:
11690  * @tb: a TypeBuilder object
11691  *
11692  * (icall)
11693  * Actually create the MonoClass that is associated with the TypeBuilder.
11694  */
11695 void
11696 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11697 {
11698         MonoError error;
11699         (void) reflection_create_internal_class (tb, &error);
11700         mono_error_set_pending_exception (&error);
11701 }
11702
11703 static MonoMarshalSpec*
11704 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11705                                 MonoReflectionMarshal *minfo, MonoError *error)
11706 {
11707         MonoMarshalSpec *res;
11708
11709         mono_error_init (error);
11710
11711         res = image_g_new0 (image, MonoMarshalSpec, 1);
11712         res->native = (MonoMarshalNative)minfo->type;
11713
11714         switch (minfo->type) {
11715         case MONO_NATIVE_LPARRAY:
11716                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11717                 if (minfo->has_size) {
11718                         res->data.array_data.param_num = minfo->param_num;
11719                         res->data.array_data.num_elem = minfo->count;
11720                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11721                 }
11722                 else {
11723                         res->data.array_data.param_num = -1;
11724                         res->data.array_data.num_elem = -1;
11725                         res->data.array_data.elem_mult = -1;
11726                 }
11727                 break;
11728
11729         case MONO_NATIVE_BYVALTSTR:
11730         case MONO_NATIVE_BYVALARRAY:
11731                 res->data.array_data.num_elem = minfo->count;
11732                 break;
11733
11734         case MONO_NATIVE_CUSTOM:
11735                 if (minfo->marshaltyperef) {
11736                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11737                         if (!is_ok (error)) {
11738                                 image_g_free (image, res);
11739                                 return NULL;
11740                         }
11741                         res->data.custom_data.custom_name =
11742                                 type_get_fully_qualified_name (marshaltyperef);
11743                 }
11744                 if (minfo->mcookie)
11745                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11746                 break;
11747
11748         default:
11749                 break;
11750         }
11751
11752         return res;
11753 }
11754 #endif /* !DISABLE_REFLECTION_EMIT */
11755
11756 MonoReflectionMarshalAsAttribute*
11757 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11758                                                         MonoMarshalSpec *spec, MonoError *error)
11759 {
11760         MonoReflectionType *rt;
11761         MonoReflectionMarshalAsAttribute *minfo;
11762         MonoType *mtype;
11763
11764         mono_error_init (error);
11765         
11766         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11767         if (!minfo)
11768                 return NULL;
11769         minfo->utype = spec->native;
11770
11771         switch (minfo->utype) {
11772         case MONO_NATIVE_LPARRAY:
11773                 minfo->array_subtype = spec->data.array_data.elem_type;
11774                 minfo->size_const = spec->data.array_data.num_elem;
11775                 if (spec->data.array_data.param_num != -1)
11776                         minfo->size_param_index = spec->data.array_data.param_num;
11777                 break;
11778
11779         case MONO_NATIVE_BYVALTSTR:
11780         case MONO_NATIVE_BYVALARRAY:
11781                 minfo->size_const = spec->data.array_data.num_elem;
11782                 break;
11783
11784         case MONO_NATIVE_CUSTOM:
11785                 if (spec->data.custom_data.custom_name) {
11786                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11787                         return_val_if_nok  (error, NULL);
11788
11789                         if (mtype) {
11790                                 rt = mono_type_get_object_checked (domain, mtype, error);
11791                                 if (!rt)
11792                                         return NULL;
11793
11794                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11795                         }
11796
11797                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11798                 }
11799                 if (spec->data.custom_data.cookie)
11800                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11801                 break;
11802
11803         default:
11804                 break;
11805         }
11806
11807         return minfo;
11808 }
11809
11810 #ifndef DISABLE_REFLECTION_EMIT
11811 static MonoMethod*
11812 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11813                                          ReflectionMethodBuilder *rmb,
11814                                          MonoMethodSignature *sig,
11815                                          MonoError *error)
11816 {
11817         MonoMethod *m;
11818         MonoMethodWrapper *wrapperm;
11819         MonoMarshalSpec **specs;
11820         MonoReflectionMethodAux *method_aux;
11821         MonoImage *image;
11822         gboolean dynamic;
11823         int i;
11824
11825         mono_error_init (error);
11826         /*
11827          * Methods created using a MethodBuilder should have their memory allocated
11828          * inside the image mempool, while dynamic methods should have their memory
11829          * malloc'd.
11830          */
11831         dynamic = rmb->refs != NULL;
11832         image = dynamic ? NULL : klass->image;
11833
11834         if (!dynamic)
11835                 g_assert (!klass->generic_class);
11836
11837         mono_loader_lock ();
11838
11839         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11840                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11841                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11842         else
11843                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11844
11845         wrapperm = (MonoMethodWrapper*)m;
11846
11847         m->dynamic = dynamic;
11848         m->slot = -1;
11849         m->flags = rmb->attrs;
11850         m->iflags = rmb->iattrs;
11851         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11852         m->klass = klass;
11853         m->signature = sig;
11854         m->sre_method = TRUE;
11855         m->skip_visibility = rmb->skip_visibility;
11856         if (rmb->table_idx)
11857                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11858
11859         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11860                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11861                         m->string_ctor = 1;
11862
11863                 m->signature->pinvoke = 1;
11864         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11865                 m->signature->pinvoke = 1;
11866
11867                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11868
11869                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, error) : image_strdup (image, m->name);
11870                 mono_error_assert_ok (error);
11871                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, error);
11872                 mono_error_assert_ok (error);
11873                 
11874                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11875
11876                 if (image_is_dynamic (klass->image))
11877                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11878
11879                 mono_loader_unlock ();
11880
11881                 return m;
11882         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11883                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11884                 MonoMethodHeader *header;
11885                 guint32 code_size;
11886                 gint32 max_stack, i;
11887                 gint32 num_locals = 0;
11888                 gint32 num_clauses = 0;
11889                 guint8 *code;
11890
11891                 if (rmb->ilgen) {
11892                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11893                         code_size = rmb->ilgen->code_len;
11894                         max_stack = rmb->ilgen->max_stack;
11895                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11896                         if (rmb->ilgen->ex_handlers)
11897                                 num_clauses = method_count_clauses (rmb->ilgen);
11898                 } else {
11899                         if (rmb->code) {
11900                                 code = mono_array_addr (rmb->code, guint8, 0);
11901                                 code_size = mono_array_length (rmb->code);
11902                                 /* we probably need to run a verifier on the code... */
11903                                 max_stack = 8; 
11904                         }
11905                         else {
11906                                 code = NULL;
11907                                 code_size = 0;
11908                                 max_stack = 8;
11909                         }
11910                 }
11911
11912                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11913                 header->code_size = code_size;
11914                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11915                 memcpy ((char*)header->code, code, code_size);
11916                 header->max_stack = max_stack;
11917                 header->init_locals = rmb->init_locals;
11918                 header->num_locals = num_locals;
11919
11920                 for (i = 0; i < num_locals; ++i) {
11921                         MonoReflectionLocalBuilder *lb = 
11922                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11923
11924                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11925                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
11926                         mono_error_assert_ok (error);
11927                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11928                 }
11929
11930                 header->num_clauses = num_clauses;
11931                 if (num_clauses) {
11932                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11933                                                                  rmb->ilgen, num_clauses, error);
11934                         mono_error_assert_ok (error);
11935                 }
11936
11937                 wrapperm->header = header;
11938         }
11939
11940         if (rmb->generic_params) {
11941                 int count = mono_array_length (rmb->generic_params);
11942                 MonoGenericContainer *container = rmb->generic_container;
11943
11944                 g_assert (container);
11945
11946                 container->type_argc = count;
11947                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11948                 container->owner.method = m;
11949                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11950
11951                 m->is_generic = TRUE;
11952                 mono_method_set_generic_container (m, container);
11953
11954                 for (i = 0; i < count; i++) {
11955                         MonoReflectionGenericParam *gp =
11956                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11957                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
11958                         mono_error_assert_ok (error);
11959                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11960                         container->type_params [i] = *param;
11961                 }
11962
11963                 /*
11964                  * The method signature might have pointers to generic parameters that belong to other methods.
11965                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11966                  * generic parameters.
11967                  */
11968                 for (i = 0; i < m->signature->param_count; ++i) {
11969                         MonoType *t = m->signature->params [i];
11970                         if (t->type == MONO_TYPE_MVAR) {
11971                                 MonoGenericParam *gparam =  t->data.generic_param;
11972                                 if (gparam->num < count) {
11973                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11974                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11975                                 }
11976
11977                         }
11978                 }
11979
11980                 if (klass->generic_container) {
11981                         container->parent = klass->generic_container;
11982                         container->context.class_inst = klass->generic_container->context.class_inst;
11983                 }
11984                 container->context.method_inst = mono_get_shared_generic_inst (container);
11985         }
11986
11987         if (rmb->refs) {
11988                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11989                 int i;
11990                 void **data;
11991
11992                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11993
11994                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11995                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11996                 for (i = 0; i < rmb->nrefs; ++i)
11997                         data [i + 1] = rmb->refs [i];
11998         }
11999
12000         method_aux = NULL;
12001
12002         /* Parameter info */
12003         if (rmb->pinfo) {
12004                 if (!method_aux)
12005                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12006                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
12007                 for (i = 0; i <= m->signature->param_count; ++i) {
12008                         MonoReflectionParamBuilder *pb;
12009                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12010                                 if ((i > 0) && (pb->attrs)) {
12011                                         /* Make a copy since it might point to a shared type structure */
12012                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
12013                                         m->signature->params [i - 1]->attrs = pb->attrs;
12014                                 }
12015
12016                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
12017                                         MonoDynamicImage *assembly;
12018                                         guint32 idx, len;
12019                                         MonoTypeEnum def_type;
12020                                         char *p;
12021                                         const char *p2;
12022
12023                                         if (!method_aux->param_defaults) {
12024                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
12025                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
12026                                         }
12027                                         assembly = (MonoDynamicImage*)klass->image;
12028                                         idx = encode_constant (assembly, pb->def_value, &def_type);
12029                                         /* Copy the data from the blob since it might get realloc-ed */
12030                                         p = assembly->blob.data + idx;
12031                                         len = mono_metadata_decode_blob_size (p, &p2);
12032                                         len += p2 - p;
12033                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12034                                         method_aux->param_default_types [i] = def_type;
12035                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12036                                 }
12037
12038                                 if (pb->name) {
12039                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, error);
12040                                         mono_error_assert_ok (error);
12041                                 }
12042                                 if (pb->cattrs) {
12043                                         if (!method_aux->param_cattr)
12044                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12045                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12046                                 }
12047                         }
12048                 }
12049         }
12050
12051         /* Parameter marshalling */
12052         specs = NULL;
12053         if (rmb->pinfo)         
12054                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12055                         MonoReflectionParamBuilder *pb;
12056                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12057                                 if (pb->marshal_info) {
12058                                         if (specs == NULL)
12059                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12060                                         specs [pb->position] = 
12061                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
12062                                         if (!is_ok (error)) {
12063                                                 mono_loader_unlock ();
12064                                                 image_g_free (image, specs);
12065                                                 /* FIXME: if image is NULL, this leaks all the other stuff we alloc'd in this function */
12066                                                 return NULL;
12067                                         }
12068                                 }
12069                         }
12070                 }
12071         if (specs != NULL) {
12072                 if (!method_aux)
12073                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12074                 method_aux->param_marshall = specs;
12075         }
12076
12077         if (image_is_dynamic (klass->image) && method_aux)
12078                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12079
12080         mono_loader_unlock ();
12081
12082         return m;
12083 }       
12084
12085 static MonoMethod*
12086 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12087 {
12088         ReflectionMethodBuilder rmb;
12089         MonoMethodSignature *sig;
12090
12091         mono_loader_lock ();
12092         g_assert (klass->image != NULL);
12093         sig = ctor_builder_to_signature (klass->image, mb, error);
12094         mono_loader_unlock ();
12095         return_val_if_nok (error, NULL);
12096
12097         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12098                 return NULL;
12099
12100         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12101         return_val_if_nok (error, NULL);
12102         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12103
12104         /* If we are in a generic class, we might be called multiple times from inflate_method */
12105         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12106                 /* ilgen is no longer needed */
12107                 mb->ilgen = NULL;
12108         }
12109
12110         return mb->mhandle;
12111 }
12112
12113 static MonoMethod*
12114 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12115 {
12116         ReflectionMethodBuilder rmb;
12117         MonoMethodSignature *sig;
12118
12119         mono_error_init (error);
12120
12121         mono_loader_lock ();
12122         g_assert (klass->image != NULL);
12123         sig = method_builder_to_signature (klass->image, mb, error);
12124         mono_loader_unlock ();
12125         return_val_if_nok (error, NULL);
12126
12127         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12128                 return NULL;
12129
12130         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
12131         return_val_if_nok (error, NULL);
12132         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12133
12134         /* If we are in a generic class, we might be called multiple times from inflate_method */
12135         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12136                 /* ilgen is no longer needed */
12137                 mb->ilgen = NULL;
12138         }
12139         return mb->mhandle;
12140 }
12141
12142 static MonoClassField*
12143 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12144 {
12145         MonoClassField *field;
12146         MonoType *custom;
12147
12148         mono_error_init (error);
12149
12150         field = g_new0 (MonoClassField, 1);
12151
12152         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12153         mono_error_assert_ok (error);
12154         if (fb->attrs || fb->modreq || fb->modopt) {
12155                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12156                 if (!is_ok (error)) {
12157                         g_free (field);
12158                         return NULL;
12159                 }
12160                 field->type = mono_metadata_type_dup (NULL, type);
12161                 field->type->attrs = fb->attrs;
12162
12163                 g_assert (image_is_dynamic (klass->image));
12164                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12165                 g_free (field->type);
12166                 if (!is_ok (error)) {
12167                         g_free (field);
12168                         return NULL;
12169                 }
12170                 field->type = mono_metadata_type_dup (klass->image, custom);
12171                 g_free (custom);
12172         } else {
12173                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12174                 if (!is_ok (error)) {
12175                         g_free (field);
12176                         return NULL;
12177                 }
12178         }
12179         if (fb->offset != -1)
12180                 field->offset = fb->offset;
12181         field->parent = klass;
12182         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12183
12184         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12185
12186         return field;
12187 }
12188 #endif
12189
12190 /**
12191  * mono_reflection_bind_generic_parameters:
12192  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12193  * @type_args: the number of type arguments to bind
12194  * @types: array of type arguments
12195  * @error: set on error
12196  *
12197  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12198  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12199  */
12200 MonoType*
12201 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12202 {
12203         MonoClass *klass;
12204         MonoReflectionTypeBuilder *tb = NULL;
12205         gboolean is_dynamic = FALSE;
12206         MonoClass *geninst;
12207
12208         mono_error_init (error);
12209         
12210         mono_loader_lock ();
12211
12212         if (is_sre_type_builder (mono_object_class (type))) {
12213                 tb = (MonoReflectionTypeBuilder *) type;
12214
12215                 is_dynamic = TRUE;
12216         } else if (is_sre_generic_instance (mono_object_class (type))) {
12217                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12218                 MonoReflectionType *gtd = rgi->generic_type;
12219
12220                 if (is_sre_type_builder (mono_object_class (gtd))) {
12221                         tb = (MonoReflectionTypeBuilder *)gtd;
12222                         is_dynamic = TRUE;
12223                 }
12224         }
12225
12226         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12227         if (tb && tb->generic_container) {
12228                 if (!mono_reflection_create_generic_class (tb, error)) {
12229                         mono_loader_unlock ();
12230                         return NULL;
12231                 }
12232         }
12233
12234         MonoType *t = mono_reflection_type_get_handle (type, error);
12235         if (!is_ok (error)) {
12236                 mono_loader_unlock ();
12237                 return NULL;
12238         }
12239
12240         klass = mono_class_from_mono_type (t);
12241         if (!klass->generic_container) {
12242                 mono_loader_unlock ();
12243                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12244                 return NULL;
12245         }
12246
12247         if (klass->wastypebuilder) {
12248                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12249
12250                 is_dynamic = TRUE;
12251         }
12252
12253         mono_loader_unlock ();
12254
12255         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12256
12257         return &geninst->byval_arg;
12258 }
12259
12260 MonoClass*
12261 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12262 {
12263         MonoGenericClass *gclass;
12264         MonoGenericInst *inst;
12265
12266         g_assert (klass->generic_container);
12267
12268         inst = mono_metadata_get_generic_inst (type_argc, types);
12269         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12270
12271         return mono_generic_class_get_class (gclass);
12272 }
12273
12274 static MonoReflectionMethod*
12275 reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
12276 {
12277         MonoClass *klass;
12278         MonoMethod *method, *inflated;
12279         MonoMethodInflated *imethod;
12280         MonoGenericContext tmp_context;
12281         MonoGenericInst *ginst;
12282         MonoType **type_argv;
12283         int count, i;
12284
12285         mono_error_init (error);
12286
12287         /*FIXME but this no longer should happen*/
12288         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12289 #ifndef DISABLE_REFLECTION_EMIT
12290                 MonoReflectionMethodBuilder *mb = NULL;
12291                 MonoType *tb;
12292                 MonoClass *klass;
12293
12294                 mb = (MonoReflectionMethodBuilder *) rmethod;
12295                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, error);
12296                 return_val_if_nok (error, NULL);
12297                 klass = mono_class_from_mono_type (tb);
12298
12299                 method = methodbuilder_to_mono_method (klass, mb, error);
12300                 return_val_if_nok (error, NULL);
12301 #else
12302                 g_assert_not_reached ();
12303                 method = NULL;
12304 #endif
12305         } else {
12306                 method = rmethod->method;
12307         }
12308
12309         klass = method->klass;
12310
12311         if (method->is_inflated)
12312                 method = ((MonoMethodInflated *) method)->declaring;
12313
12314         count = mono_method_signature (method)->generic_param_count;
12315         if (count != mono_array_length (types))
12316                 return NULL;
12317
12318         type_argv = g_new0 (MonoType *, count);
12319         for (i = 0; i < count; i++) {
12320                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12321                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
12322                 if (!is_ok (error)) {
12323                         g_free (type_argv);
12324                         return NULL;
12325                 }
12326         }
12327         ginst = mono_metadata_get_generic_inst (count, type_argv);
12328         g_free (type_argv);
12329
12330         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12331         tmp_context.method_inst = ginst;
12332
12333         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
12334         mono_error_assert_ok (error);
12335         imethod = (MonoMethodInflated *) inflated;
12336
12337         /*FIXME but I think this is no longer necessary*/
12338         if (image_is_dynamic (method->klass->image)) {
12339                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12340                 /*
12341                  * This table maps metadata structures representing inflated methods/fields
12342                  * to the reflection objects representing their generic definitions.
12343                  */
12344                 mono_image_lock ((MonoImage*)image);
12345                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12346                 mono_image_unlock ((MonoImage*)image);
12347         }
12348
12349         if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
12350                 mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
12351                 return NULL;
12352         }
12353         
12354         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
12355         return ret;
12356 }
12357
12358 MonoReflectionMethod*
12359 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12360 {
12361         MonoError error;
12362         MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
12363         mono_error_set_pending_exception (&error);
12364         return result;
12365 }
12366
12367
12368 #ifndef DISABLE_REFLECTION_EMIT
12369
12370 static MonoMethod *
12371 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12372 {
12373         MonoMethodInflated *imethod;
12374         MonoGenericContext *context;
12375         int i;
12376
12377         /*
12378          * With generic code sharing the klass might not be inflated.
12379          * This can happen because classes inflated with their own
12380          * type arguments are "normalized" to the uninflated class.
12381          */
12382         if (!klass->generic_class)
12383                 return method;
12384
12385         context = mono_class_get_context (klass);
12386
12387         if (klass->method.count && klass->methods) {
12388                 /* Find the already created inflated method */
12389                 for (i = 0; i < klass->method.count; ++i) {
12390                         g_assert (klass->methods [i]->is_inflated);
12391                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12392                                 break;
12393                 }
12394                 g_assert (i < klass->method.count);
12395                 imethod = (MonoMethodInflated*)klass->methods [i];
12396         } else {
12397                 MonoError error;
12398                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12399                 mono_error_assert_ok (&error);
12400         }
12401
12402         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12403                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12404
12405                 mono_image_lock ((MonoImage*)image);
12406                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12407                 mono_image_unlock ((MonoImage*)image);
12408         }
12409         return (MonoMethod *) imethod;
12410 }
12411
12412 static MonoMethod *
12413 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12414 {
12415         MonoMethod *method;
12416         MonoClass *gklass;
12417
12418         mono_error_init (error);
12419
12420         MonoClass *type_class = mono_object_class (type);
12421
12422         if (is_sre_generic_instance (type_class)) {
12423                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12424                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12425                 return_val_if_nok (error, NULL);
12426                 gklass = mono_class_from_mono_type (generic_type);
12427         } else if (is_sre_type_builder (type_class)) {
12428                 MonoType *t = mono_reflection_type_get_handle (type, error);
12429                 return_val_if_nok (error, NULL);
12430                 gklass = mono_class_from_mono_type (t);
12431         } else if (type->type) {
12432                 gklass = mono_class_from_mono_type (type->type);
12433                 gklass = mono_class_get_generic_type_definition (gklass);
12434         } else {
12435                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12436         }
12437
12438         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12439                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12440                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12441                 else {
12442                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12443                         if (!method)
12444                                 return NULL;
12445                 }
12446         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12447                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12448                 if (!method)
12449                         return NULL;
12450         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12451                 method = ((MonoReflectionMethod *) obj)->method;
12452         else {
12453                 method = NULL; /* prevent compiler warning */
12454                 g_error ("can't handle type %s", obj->vtable->klass->name);
12455         }
12456
12457         MonoType *t = mono_reflection_type_get_handle (type, error);
12458         return_val_if_nok (error, NULL);
12459         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12460 }
12461
12462 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12463 static gboolean
12464 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12465 {
12466         MonoGenericClass *gclass;
12467         MonoDynamicGenericClass *dgclass;
12468         MonoClass *klass, *gklass;
12469         MonoType *gtype;
12470         int i;
12471
12472         mono_error_init (error);
12473
12474         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12475         return_val_if_nok (error, FALSE);
12476         klass = mono_class_from_mono_type (gtype);
12477         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12478         gclass = gtype->data.generic_class;
12479
12480         if (!gclass->is_dynamic)
12481                 return TRUE;
12482
12483         dgclass = (MonoDynamicGenericClass *) gclass;
12484
12485         if (dgclass->initialized)
12486                 return TRUE;
12487
12488         gklass = gclass->container_class;
12489         mono_class_init (gklass);
12490
12491         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12492
12493         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12494         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12495         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12496
12497         for (i = 0; i < dgclass->count_fields; i++) {
12498                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12499                 MonoClassField *field, *inflated_field = NULL;
12500
12501                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12502                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12503                         return_val_if_nok (error, FALSE);
12504                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12505                         field = ((MonoReflectionField *) obj)->field;
12506                 else {
12507                         field = NULL; /* prevent compiler warning */
12508                         g_assert_not_reached ();
12509                 }
12510
12511                 dgclass->fields [i] = *field;
12512                 dgclass->fields [i].parent = klass;
12513                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12514                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12515                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12516                 dgclass->field_generic_types [i] = field->type;
12517                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12518                 dgclass->field_objects [i] = obj;
12519
12520                 if (inflated_field) {
12521                         g_free (inflated_field);
12522                 } else {
12523                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12524                 }
12525         }
12526
12527         dgclass->initialized = TRUE;
12528         return TRUE;
12529 }
12530
12531 void
12532 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12533 {
12534         MonoError error;
12535         (void) reflection_generic_class_initialize (type, fields, &error);
12536         mono_error_set_pending_exception (&error);
12537 }
12538
12539 void
12540 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12541 {
12542         MonoDynamicGenericClass *dgclass;
12543         int i;
12544
12545         g_assert (gclass->is_dynamic);
12546
12547         dgclass = (MonoDynamicGenericClass *)gclass;
12548
12549         for (i = 0; i < dgclass->count_fields; ++i) {
12550                 MonoClassField *field = dgclass->fields + i;
12551                 mono_metadata_free_type (field->type);
12552                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12553         }
12554 }
12555
12556 /**
12557  * fix_partial_generic_class:
12558  * @klass: a generic instantiation MonoClass
12559  * @error: set on error
12560  *
12561  * Assumes that the generic container of @klass has its vtable
12562  * initialized, and updates the parent class, insterfaces, methods and
12563  * fields of @klass by inflating the types using the generic context.
12564  *
12565  * On success returns TRUE, on failure returns FALSE and sets @error.
12566  *
12567  */
12568 static gboolean
12569 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12570 {
12571         MonoClass *gklass = klass->generic_class->container_class;
12572         MonoDynamicGenericClass *dgclass;
12573         int i;
12574
12575         mono_error_init (error);
12576
12577         if (klass->wastypebuilder)
12578                 return TRUE;
12579
12580         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12581         if (klass->parent != gklass->parent) {
12582                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12583                 if (mono_error_ok (error)) {
12584                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12585                         mono_metadata_free_type (parent_type);
12586                         if (parent != klass->parent) {
12587                                 /*fool mono_class_setup_parent*/
12588                                 klass->supertypes = NULL;
12589                                 mono_class_setup_parent (klass, parent);
12590                         }
12591                 } else {
12592                         if (gklass->wastypebuilder)
12593                                 klass->wastypebuilder = TRUE;
12594                         return FALSE;
12595                 }
12596         }
12597
12598         if (!dgclass->initialized)
12599                 return TRUE;
12600
12601         if (klass->method.count != gklass->method.count) {
12602                 klass->method.count = gklass->method.count;
12603                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12604
12605                 for (i = 0; i < klass->method.count; i++) {
12606                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12607                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12608                         mono_error_assert_ok (error);
12609                 }
12610         }
12611
12612         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12613                 klass->interface_count = gklass->interface_count;
12614                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12615                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12616
12617                 for (i = 0; i < gklass->interface_count; ++i) {
12618                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12619                         return_val_if_nok (error, FALSE);
12620
12621                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12622                         mono_metadata_free_type (iface_type);
12623
12624                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12625                                 return FALSE;
12626                 }
12627                 klass->interfaces_inited = 1;
12628         }
12629
12630         if (klass->field.count != gklass->field.count) {
12631                 klass->field.count = gklass->field.count;
12632                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12633
12634                 for (i = 0; i < klass->field.count; i++) {
12635                         klass->fields [i] = gklass->fields [i];
12636                         klass->fields [i].parent = klass;
12637                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12638                         return_val_if_nok (error, FALSE);
12639                 }
12640         }
12641
12642         /*We can only finish with this klass once it's parent has as well*/
12643         if (gklass->wastypebuilder)
12644                 klass->wastypebuilder = TRUE;
12645         return TRUE;
12646 }
12647
12648 /**
12649  * ensure_generic_class_runtime_vtable:
12650  * @klass a generic class
12651  * @error set on error
12652  *
12653  * Ensures that the generic container of @klass has a vtable and
12654  * returns TRUE on success.  On error returns FALSE and sets @error.
12655  */
12656 static gboolean
12657 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12658 {
12659         MonoClass *gklass = klass->generic_class->container_class;
12660
12661         mono_error_init (error);
12662
12663         if (!ensure_runtime_vtable (gklass, error))
12664                 return FALSE;
12665
12666         return fix_partial_generic_class (klass, error);
12667 }
12668
12669 /**
12670  * ensure_runtime_vtable:
12671  * @klass the class
12672  * @error set on error
12673  *
12674  * Ensures that @klass has a vtable and returns TRUE on success. On
12675  * error returns FALSE and sets @error.
12676  */
12677 static gboolean
12678 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12679 {
12680         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12681         int i, num, j;
12682
12683         mono_error_init (error);
12684
12685         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12686                 return TRUE;
12687         if (klass->parent)
12688                 if (!ensure_runtime_vtable (klass->parent, error))
12689                         return FALSE;
12690
12691         if (tb) {
12692                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12693                 num += tb->num_methods;
12694                 klass->method.count = num;
12695                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12696                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12697                 for (i = 0; i < num; ++i) {
12698                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12699                         if (!ctor)
12700                                 return FALSE;
12701                         klass->methods [i] = ctor;
12702                 }
12703                 num = tb->num_methods;
12704                 j = i;
12705                 for (i = 0; i < num; ++i) {
12706                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12707                         if (!meth)
12708                                 return FALSE;
12709                         klass->methods [j++] = meth;
12710                 }
12711         
12712                 if (tb->interfaces) {
12713                         klass->interface_count = mono_array_length (tb->interfaces);
12714                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12715                         for (i = 0; i < klass->interface_count; ++i) {
12716                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12717                                 return_val_if_nok (error, FALSE);
12718                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12719                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12720                                         return FALSE;
12721                         }
12722                         klass->interfaces_inited = 1;
12723                 }
12724         } else if (klass->generic_class){
12725                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12726                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12727                         return FALSE;
12728                 }
12729         }
12730
12731         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12732                 int slot_num = 0;
12733                 for (i = 0; i < klass->method.count; ++i) {
12734                         MonoMethod *im = klass->methods [i];
12735                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12736                                 im->slot = slot_num++;
12737                 }
12738                 
12739                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12740                 mono_class_setup_interface_offsets (klass);
12741                 mono_class_setup_interface_id (klass);
12742         }
12743
12744         /*
12745          * The generic vtable is needed even if image->run is not set since some
12746          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12747          * method->slot being defined.
12748          */
12749
12750         /* 
12751          * tb->methods could not be freed since it is used for determining 
12752          * overrides during dynamic vtable construction.
12753          */
12754
12755         return TRUE;
12756 }
12757
12758 static MonoMethod*
12759 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12760 {
12761         mono_error_init (error);
12762         MonoClass *klass = mono_object_class (method);
12763         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12764                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12765                 return sr_method->method;
12766         }
12767         if (is_sre_method_builder (klass)) {
12768                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12769                 return mb->mhandle;
12770         }
12771         if (is_sre_method_on_tb_inst (klass)) {
12772                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12773                 MonoMethod *result;
12774                 /*FIXME move this to a proper method and unify with resolve_object*/
12775                 if (m->method_args) {
12776                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12777                 } else {
12778                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12779                         return_val_if_nok (error, NULL);
12780                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12781                         MonoMethod *mono_method;
12782
12783                         if (is_sre_method_builder (mono_object_class (m->mb)))
12784                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12785                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12786                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12787                         else
12788                                 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)));
12789
12790                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12791                 }
12792                 return result;
12793         }
12794
12795         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12796         return NULL;
12797 }
12798
12799 void
12800 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12801 {
12802         MonoReflectionTypeBuilder *tb;
12803         int i, j, onum;
12804         MonoReflectionMethod *m;
12805
12806         mono_error_init (error);
12807         *overrides = NULL;
12808         *num_overrides = 0;
12809
12810         g_assert (image_is_dynamic (klass->image));
12811
12812         if (!mono_class_get_ref_info (klass))
12813                 return;
12814
12815         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12816
12817         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12818
12819         onum = 0;
12820         if (tb->methods) {
12821                 for (i = 0; i < tb->num_methods; ++i) {
12822                         MonoReflectionMethodBuilder *mb = 
12823                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12824                         if (mb->override_methods)
12825                                 onum += mono_array_length (mb->override_methods);
12826                 }
12827         }
12828
12829         if (onum) {
12830                 *overrides = g_new0 (MonoMethod*, onum * 2);
12831
12832                 onum = 0;
12833                 for (i = 0; i < tb->num_methods; ++i) {
12834                         MonoReflectionMethodBuilder *mb = 
12835                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12836                         if (mb->override_methods) {
12837                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12838                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12839
12840                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12841                                         return_if_nok (error);
12842                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12843
12844                                         g_assert (mb->mhandle);
12845
12846                                         onum ++;
12847                                 }
12848                         }
12849                 }
12850         }
12851
12852         *num_overrides = onum;
12853 }
12854
12855 static void
12856 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12857 {
12858         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12859         MonoReflectionFieldBuilder *fb;
12860         MonoClassField *field;
12861         MonoImage *image = klass->image;
12862         const char *p, *p2;
12863         int i;
12864         guint32 len, idx, real_size = 0;
12865
12866         klass->field.count = tb->num_fields;
12867         klass->field.first = 0;
12868
12869         mono_error_init (error);
12870
12871         if (tb->class_size) {
12872                 if ((tb->packing_size & 0xffffff00) != 0) {
12873                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12874                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12875                         return;
12876                 }
12877                 klass->packing_size = tb->packing_size;
12878                 real_size = klass->instance_size + tb->class_size;
12879         }
12880
12881         if (!klass->field.count) {
12882                 klass->instance_size = MAX (klass->instance_size, real_size);
12883                 return;
12884         }
12885         
12886         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12887         mono_class_alloc_ext (klass);
12888         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12889         /*
12890         This is, guess what, a hack.
12891         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12892         On the static path no field class is resolved, only types are built. This is the right thing to do
12893         but we suck.
12894         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12895         */
12896         klass->size_inited = 1;
12897
12898         for (i = 0; i < klass->field.count; ++i) {
12899                 MonoArray *rva_data;
12900                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12901                 field = &klass->fields [i];
12902                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12903                 if (!mono_error_ok (error))
12904                         return;
12905                 if (fb->attrs) {
12906                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12907                         return_if_nok (error);
12908                         field->type = mono_metadata_type_dup (klass->image, type);
12909                         field->type->attrs = fb->attrs;
12910                 } else {
12911                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12912                         return_if_nok (error);
12913                 }
12914
12915                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12916                         char *base = mono_array_addr (rva_data, char, 0);
12917                         size_t size = mono_array_length (rva_data);
12918                         char *data = (char *)mono_image_alloc (klass->image, size);
12919                         memcpy (data, base, size);
12920                         klass->ext->field_def_values [i].data = data;
12921                 }
12922                 if (fb->offset != -1)
12923                         field->offset = fb->offset;
12924                 field->parent = klass;
12925                 fb->handle = field;
12926                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12927
12928                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12929                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12930                 }
12931                 if (fb->def_value) {
12932                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12933                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12934                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12935                         /* Copy the data from the blob since it might get realloc-ed */
12936                         p = assembly->blob.data + idx;
12937                         len = mono_metadata_decode_blob_size (p, &p2);
12938                         len += p2 - p;
12939                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12940                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12941                 }
12942         }
12943
12944         klass->instance_size = MAX (klass->instance_size, real_size);
12945         mono_class_layout_fields (klass, klass->instance_size);
12946 }
12947
12948 static void
12949 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12950 {
12951         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12952         MonoReflectionPropertyBuilder *pb;
12953         MonoImage *image = klass->image;
12954         MonoProperty *properties;
12955         int i;
12956
12957         mono_error_init (error);
12958
12959         if (!klass->ext)
12960                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12961
12962         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12963         klass->ext->property.first = 0;
12964
12965         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12966         klass->ext->properties = properties;
12967         for (i = 0; i < klass->ext->property.count; ++i) {
12968                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12969                 properties [i].parent = klass;
12970                 properties [i].attrs = pb->attrs;
12971                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12972                 if (!mono_error_ok (error))
12973                         return;
12974                 if (pb->get_method)
12975                         properties [i].get = pb->get_method->mhandle;
12976                 if (pb->set_method)
12977                         properties [i].set = pb->set_method->mhandle;
12978
12979                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12980                 if (pb->def_value) {
12981                         guint32 len, idx;
12982                         const char *p, *p2;
12983                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12984                         if (!klass->ext->prop_def_values)
12985                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12986                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12987                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12988                         /* Copy the data from the blob since it might get realloc-ed */
12989                         p = assembly->blob.data + idx;
12990                         len = mono_metadata_decode_blob_size (p, &p2);
12991                         len += p2 - p;
12992                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12993                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12994                 }
12995         }
12996 }
12997
12998 static MonoReflectionEvent *
12999 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
13000 {
13001         mono_error_init (error);
13002
13003         MonoEvent *event = g_new0 (MonoEvent, 1);
13004         MonoClass *klass;
13005
13006         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13007         if (!is_ok (error)) {
13008                 g_free (event);
13009                 return NULL;
13010         }
13011         klass = mono_class_from_mono_type (type);
13012
13013         event->parent = klass;
13014         event->attrs = eb->attrs;
13015         event->name = mono_string_to_utf8 (eb->name);
13016         if (eb->add_method)
13017                 event->add = eb->add_method->mhandle;
13018         if (eb->remove_method)
13019                 event->remove = eb->remove_method->mhandle;
13020         if (eb->raise_method)
13021                 event->raise = eb->raise_method->mhandle;
13022
13023 #ifndef MONO_SMALL_CONFIG
13024         if (eb->other_methods) {
13025                 int j;
13026                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
13027                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13028                         MonoReflectionMethodBuilder *mb = 
13029                                 mono_array_get (eb->other_methods,
13030                                                 MonoReflectionMethodBuilder*, j);
13031                         event->other [j] = mb->mhandle;
13032                 }
13033         }
13034 #endif
13035
13036         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
13037         if (!is_ok (error)) {
13038 #ifndef MONO_SMALL_CONFIG
13039                 g_free (event->other);
13040 #endif
13041                 g_free (event);
13042                 return NULL;
13043         }
13044         return ev_obj;
13045 }
13046
13047 MonoReflectionEvent *
13048 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13049 {
13050         MonoError error;
13051         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13052         mono_error_set_pending_exception (&error);
13053         return result;
13054 }
13055
13056 static void
13057 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13058 {
13059         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13060         MonoReflectionEventBuilder *eb;
13061         MonoImage *image = klass->image;
13062         MonoEvent *events;
13063         int i;
13064
13065         mono_error_init (error);
13066
13067         if (!klass->ext)
13068                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13069
13070         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13071         klass->ext->event.first = 0;
13072
13073         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13074         klass->ext->events = events;
13075         for (i = 0; i < klass->ext->event.count; ++i) {
13076                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13077                 events [i].parent = klass;
13078                 events [i].attrs = eb->attrs;
13079                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13080                 if (!mono_error_ok (error))
13081                         return;
13082                 if (eb->add_method)
13083                         events [i].add = eb->add_method->mhandle;
13084                 if (eb->remove_method)
13085                         events [i].remove = eb->remove_method->mhandle;
13086                 if (eb->raise_method)
13087                         events [i].raise = eb->raise_method->mhandle;
13088
13089 #ifndef MONO_SMALL_CONFIG
13090                 if (eb->other_methods) {
13091                         int j;
13092                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13093                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13094                                 MonoReflectionMethodBuilder *mb = 
13095                                         mono_array_get (eb->other_methods,
13096                                                                         MonoReflectionMethodBuilder*, j);
13097                                 events [i].other [j] = mb->mhandle;
13098                         }
13099                 }
13100 #endif
13101                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13102         }
13103 }
13104
13105 struct remove_instantiations_user_data
13106 {
13107         MonoClass *klass;
13108         MonoError *error;
13109 };
13110
13111 static gboolean
13112 remove_instantiations_of_and_ensure_contents (gpointer key,
13113                                                   gpointer value,
13114                                                   gpointer user_data)
13115 {
13116         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13117         MonoType *type = (MonoType*)key;
13118         MonoClass *klass = data->klass;
13119         gboolean already_failed = !is_ok (data->error);
13120         MonoError lerror;
13121         MonoError *error = already_failed ? &lerror : data->error;
13122
13123         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13124                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13125                 //Ensure it's safe to use it.
13126                 if (!fix_partial_generic_class (inst_klass, error)) {
13127                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13128                         // Marked the class with failure, but since some other instantiation already failed,
13129                         // just report that one, and swallow the error from this one.
13130                         if (already_failed)
13131                                 mono_error_cleanup (error);
13132                 }
13133                 return TRUE;
13134         } else
13135                 return FALSE;
13136 }
13137
13138 static void
13139 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13140 {
13141         mono_error_init (error);
13142         int i;
13143
13144         if (!arr)
13145                 return;
13146
13147         for (i = 0; i < mono_array_length (arr); ++i) {
13148                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13149                 if (!mono_error_ok (error))
13150                         break;
13151         }
13152 }
13153
13154 MonoReflectionType*
13155 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13156 {
13157         MonoError error;
13158         MonoClass *klass;
13159         MonoDomain* domain;
13160         MonoReflectionType* res;
13161         int i, j;
13162
13163         mono_error_init (&error);
13164
13165         domain = mono_object_domain (tb);
13166         klass = mono_class_from_mono_type (tb->type.type);
13167
13168         /*
13169          * Check for user defined Type subclasses.
13170          */
13171         RESOLVE_TYPE (tb->parent, &error);
13172         if (!is_ok (&error))
13173                 goto failure_unlocked;
13174         check_array_for_usertypes (tb->interfaces, &error);
13175         if (!is_ok (&error))
13176                 goto failure_unlocked;
13177         if (tb->fields) {
13178                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13179                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13180                         if (fb) {
13181                                 RESOLVE_TYPE (fb->type, &error);
13182                                 if (!is_ok (&error))
13183                                         goto failure_unlocked;
13184                                 check_array_for_usertypes (fb->modreq, &error);
13185                                 if (!is_ok (&error))
13186                                         goto failure_unlocked;
13187                                 check_array_for_usertypes (fb->modopt, &error);
13188                                 if (!is_ok (&error))
13189                                         goto failure_unlocked;
13190                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13191                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13192                                         if (!is_ok (&error))
13193                                                 goto failure_unlocked;
13194                                 }
13195                         }
13196                 }
13197         }
13198         if (tb->methods) {
13199                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13200                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13201                         if (mb) {
13202                                 RESOLVE_TYPE (mb->rtype, &error);
13203                                 if (!is_ok (&error))
13204                                         goto failure_unlocked;
13205                                 check_array_for_usertypes (mb->return_modreq, &error);
13206                                 if (!is_ok (&error))
13207                                         goto failure_unlocked;
13208                                 check_array_for_usertypes (mb->return_modopt, &error);
13209                                 if (!is_ok (&error))
13210                                         goto failure_unlocked;
13211                                 check_array_for_usertypes (mb->parameters, &error);
13212                                 if (!is_ok (&error))
13213                                         goto failure_unlocked;
13214                                 if (mb->param_modreq)
13215                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13216                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13217                                                 if (!is_ok (&error))
13218                                                         goto failure_unlocked;
13219                                         }
13220                                 if (mb->param_modopt)
13221                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13222                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13223                                                 if (!is_ok (&error))
13224                                                         goto failure_unlocked;
13225                                         }
13226                         }
13227                 }
13228         }
13229         if (tb->ctors) {
13230                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13231                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13232                         if (mb) {
13233                                 check_array_for_usertypes (mb->parameters, &error);
13234                                 if (!is_ok (&error))
13235                                         goto failure_unlocked;
13236                                 if (mb->param_modreq)
13237                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13238                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13239                                                 if (!is_ok (&error))
13240                                                         goto failure_unlocked;
13241                                         }
13242                                 if (mb->param_modopt)
13243                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13244                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13245                                                 if (!is_ok (&error))
13246                                                         goto failure_unlocked;
13247                                         }
13248                         }
13249                 }
13250         }
13251
13252         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13253
13254         /* 
13255          * we need to lock the domain because the lock will be taken inside
13256          * So, we need to keep the locking order correct.
13257          */
13258         mono_loader_lock ();
13259         mono_domain_lock (domain);
13260         if (klass->wastypebuilder) {
13261                 mono_domain_unlock (domain);
13262                 mono_loader_unlock ();
13263
13264                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13265                 mono_error_set_pending_exception (&error);
13266
13267                 return res;
13268         }
13269         /*
13270          * Fields to set in klass:
13271          * the various flags: delegate/unicode/contextbound etc.
13272          */
13273         klass->flags = tb->attrs;
13274         klass->has_cctor = 1;
13275         klass->has_finalize = 1;
13276         klass->has_finalize_inited = 1;
13277
13278         mono_class_setup_parent (klass, klass->parent);
13279         /* fool mono_class_setup_supertypes */
13280         klass->supertypes = NULL;
13281         mono_class_setup_supertypes (klass);
13282         mono_class_setup_mono_type (klass);
13283
13284 #if 0
13285         if (!((MonoDynamicImage*)klass->image)->run) {
13286                 if (klass->generic_container) {
13287                         /* FIXME: The code below can't handle generic classes */
13288                         klass->wastypebuilder = TRUE;
13289                         mono_loader_unlock ();
13290                         mono_domain_unlock (domain);
13291
13292                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13293                         mono_error_set_pending_exception (&error);
13294
13295                         return res;
13296                 }
13297         }
13298 #endif
13299
13300         /* enums are done right away */
13301         if (!klass->enumtype)
13302                 if (!ensure_runtime_vtable (klass, &error))
13303                         goto failure;
13304
13305         if (tb->subtypes) {
13306                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13307                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13308                         mono_class_alloc_ext (klass);
13309                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13310                         if (!is_ok (&error)) goto failure;
13311                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13312                 }
13313         }
13314
13315         klass->nested_classes_inited = TRUE;
13316
13317         /* fields and object layout */
13318         if (klass->parent) {
13319                 if (!klass->parent->size_inited)
13320                         mono_class_init (klass->parent);
13321                 klass->instance_size = klass->parent->instance_size;
13322                 klass->sizes.class_size = 0;
13323                 klass->min_align = klass->parent->min_align;
13324                 /* if the type has no fields we won't call the field_setup
13325                  * routine which sets up klass->has_references.
13326                  */
13327                 klass->has_references |= klass->parent->has_references;
13328         } else {
13329                 klass->instance_size = sizeof (MonoObject);
13330                 klass->min_align = 1;
13331         }
13332
13333         /* FIXME: handle packing_size and instance_size */
13334         typebuilder_setup_fields (klass, &error);
13335         if (!mono_error_ok (&error))
13336                 goto failure;
13337         typebuilder_setup_properties (klass, &error);
13338         if (!mono_error_ok (&error))
13339                 goto failure;
13340
13341         typebuilder_setup_events (klass, &error);
13342         if (!mono_error_ok (&error))
13343                 goto failure;
13344
13345         klass->wastypebuilder = TRUE;
13346
13347         /* 
13348          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13349          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13350          * we want to return normal System.MonoType objects, so clear these out from the cache.
13351          *
13352          * Together with this we must ensure the contents of all instances to match the created type.
13353          */
13354         if (domain->type_hash && klass->generic_container) {
13355                 struct remove_instantiations_user_data data;
13356                 data.klass = klass;
13357                 data.error = &error;
13358                 mono_error_assert_ok (&error);
13359                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13360                 if (!is_ok (&error))
13361                         goto failure;
13362         }
13363
13364         mono_domain_unlock (domain);
13365         mono_loader_unlock ();
13366
13367         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13368                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13369                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13370                 goto failure_unlocked;
13371         }
13372
13373         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13374         if (!is_ok (&error))
13375                 goto failure_unlocked;
13376
13377         g_assert (res != (MonoReflectionType*)tb);
13378
13379         return res;
13380
13381 failure:
13382         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13383         klass->wastypebuilder = TRUE;
13384         mono_domain_unlock (domain);
13385         mono_loader_unlock ();
13386 failure_unlocked:
13387         mono_error_set_pending_exception (&error);
13388         return NULL;
13389 }
13390
13391 static gboolean
13392 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13393 {
13394         MonoGenericParamFull *param;
13395         MonoImage *image;
13396         MonoClass *pklass;
13397
13398         mono_error_init (error);
13399
13400         image = &gparam->tbuilder->module->dynamic_image->image;
13401
13402         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13403
13404         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13405         mono_error_assert_ok (error);
13406         param->param.num = gparam->index;
13407
13408         if (gparam->mbuilder) {
13409                 if (!gparam->mbuilder->generic_container) {
13410                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13411                         return_val_if_nok (error, FALSE);
13412
13413                         MonoClass *klass = mono_class_from_mono_type (tb);
13414                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13415                         gparam->mbuilder->generic_container->is_method = TRUE;
13416                         /* 
13417                          * Cannot set owner.method, since the MonoMethod is not created yet.
13418                          * Set the image field instead, so type_in_image () works.
13419                          */
13420                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13421                         gparam->mbuilder->generic_container->owner.image = klass->image;
13422                 }
13423                 param->param.owner = gparam->mbuilder->generic_container;
13424         } else if (gparam->tbuilder) {
13425                 if (!gparam->tbuilder->generic_container) {
13426                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13427                         return_val_if_nok (error, FALSE);
13428                         MonoClass *klass = mono_class_from_mono_type (tb);
13429                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13430                         gparam->tbuilder->generic_container->owner.klass = klass;
13431                 }
13432                 param->param.owner = gparam->tbuilder->generic_container;
13433         }
13434
13435         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13436
13437         gparam->type.type = &pklass->byval_arg;
13438
13439         mono_class_set_ref_info (pklass, gparam);
13440         mono_image_append_class_to_reflection_info_set (pklass);
13441
13442         return TRUE;
13443 }
13444
13445 void
13446 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13447 {
13448         MonoError error;
13449         (void) reflection_initialize_generic_parameter (gparam, &error);
13450         mono_error_set_pending_exception (&error);
13451 }
13452
13453
13454 static MonoArray *
13455 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
13456 {
13457         MonoReflectionModuleBuilder *module = sig->module;
13458         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13459         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13460         guint32 buflen, i;
13461         MonoArray *result;
13462         SigBuffer buf;
13463
13464         mono_error_init (error);
13465
13466         check_array_for_usertypes (sig->arguments, error);
13467         return_val_if_nok (error, NULL);
13468
13469         sigbuffer_init (&buf, 32);
13470
13471         sigbuffer_add_value (&buf, 0x07);
13472         sigbuffer_add_value (&buf, na);
13473         if (assembly != NULL){
13474                 for (i = 0; i < na; ++i) {
13475                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13476                         encode_reflection_type (assembly, type, &buf, error);
13477                         if (!is_ok (error)) goto fail;
13478                 }
13479         }
13480
13481         buflen = buf.p - buf.buf;
13482         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13483         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13484         sigbuffer_free (&buf);
13485         return result;
13486 fail:
13487         sigbuffer_free (&buf);
13488         return NULL;
13489 }
13490
13491 MonoArray *
13492 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13493 {
13494         MonoError error;
13495         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
13496         mono_error_set_pending_exception (&error);
13497         return result;
13498 }
13499
13500 static MonoArray *
13501 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
13502 {
13503         MonoDynamicImage *assembly = sig->module->dynamic_image;
13504         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13505         guint32 buflen, i;
13506         MonoArray *result;
13507         SigBuffer buf;
13508
13509         mono_error_init (error);
13510
13511         check_array_for_usertypes (sig->arguments, error);
13512         return_val_if_nok (error, NULL);
13513
13514         sigbuffer_init (&buf, 32);
13515
13516         sigbuffer_add_value (&buf, 0x06);
13517         for (i = 0; i < na; ++i) {
13518                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13519                 encode_reflection_type (assembly, type, &buf, error);
13520                 if (!is_ok (error))
13521                         goto fail;
13522         }
13523
13524         buflen = buf.p - buf.buf;
13525         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13526         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13527         sigbuffer_free (&buf);
13528
13529         return result;
13530 fail:
13531         sigbuffer_free (&buf);
13532         return NULL;
13533 }
13534
13535 MonoArray *
13536 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13537 {
13538         MonoError error;
13539         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
13540         mono_error_set_pending_exception (&error);
13541         return result;
13542 }
13543
13544 typedef struct {
13545         MonoMethod *handle;
13546         MonoDomain *domain;
13547 } DynamicMethodReleaseData;
13548
13549 /*
13550  * The runtime automatically clean up those after finalization.
13551 */      
13552 static MonoReferenceQueue *dynamic_method_queue;
13553
13554 static void
13555 free_dynamic_method (void *dynamic_method)
13556 {
13557         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13558         MonoDomain *domain = data->domain;
13559         MonoMethod *method = data->handle;
13560         guint32 dis_link;
13561
13562         mono_domain_lock (domain);
13563         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13564         g_hash_table_remove (domain->method_to_dyn_method, method);
13565         mono_domain_unlock (domain);
13566         g_assert (dis_link);
13567         mono_gchandle_free (dis_link);
13568
13569         mono_runtime_free_method (domain, method);
13570         g_free (data);
13571 }
13572
13573 static gboolean
13574 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13575 {
13576         MonoReferenceQueue *queue;
13577         MonoMethod *handle;
13578         DynamicMethodReleaseData *release_data;
13579         ReflectionMethodBuilder rmb;
13580         MonoMethodSignature *sig;
13581         MonoClass *klass;
13582         MonoDomain *domain;
13583         GSList *l;
13584         int i;
13585
13586         mono_error_init (error);
13587
13588         if (mono_runtime_is_shutting_down ()) {
13589                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13590                 return FALSE;
13591         }
13592
13593         if (!(queue = dynamic_method_queue)) {
13594                 mono_loader_lock ();
13595                 if (!(queue = dynamic_method_queue))
13596                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13597                 mono_loader_unlock ();
13598         }
13599
13600         sig = dynamic_method_to_signature (mb, error);
13601         return_val_if_nok (error, FALSE);
13602
13603         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13604
13605         /*
13606          * Resolve references.
13607          */
13608         /* 
13609          * Every second entry in the refs array is reserved for storing handle_class,
13610          * which is needed by the ldtoken implementation in the JIT.
13611          */
13612         rmb.nrefs = mb->nrefs;
13613         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13614         for (i = 0; i < mb->nrefs; i += 2) {
13615                 MonoClass *handle_class;
13616                 gpointer ref;
13617                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13618
13619                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13620                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13621                         /*
13622                          * The referenced DynamicMethod should already be created by the managed
13623                          * code, except in the case of circular references. In that case, we store
13624                          * method in the refs array, and fix it up later when the referenced 
13625                          * DynamicMethod is created.
13626                          */
13627                         if (method->mhandle) {
13628                                 ref = method->mhandle;
13629                         } else {
13630                                 /* FIXME: GC object stored in unmanaged memory */
13631                                 ref = method;
13632
13633                                 /* FIXME: GC object stored in unmanaged memory */
13634                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13635                         }
13636                         handle_class = mono_defaults.methodhandle_class;
13637                 } else {
13638                         MonoException *ex = NULL;
13639                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13640                         if (!is_ok  (error)) {
13641                                 g_free (rmb.refs);
13642                                 return FALSE;
13643                         }
13644                         if (!ref)
13645                                 ex = mono_get_exception_type_load (NULL, NULL);
13646                         else if (mono_security_core_clr_enabled ())
13647                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13648
13649                         if (ex) {
13650                                 g_free (rmb.refs);
13651                                 mono_error_set_exception_instance (error, ex);
13652                                 return FALSE;
13653                         }
13654                 }
13655
13656                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13657                 rmb.refs [i + 1] = handle_class;
13658         }               
13659
13660         if (mb->owner) {
13661                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13662                 if (!is_ok (error)) {
13663                         g_free (rmb.refs);
13664                         return FALSE;
13665                 }
13666                 klass = mono_class_from_mono_type (owner_type);
13667         } else {
13668                 klass = mono_defaults.object_class;
13669         }
13670
13671         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
13672         g_free (rmb.refs);
13673         return_val_if_nok (error, FALSE);
13674
13675         release_data = g_new (DynamicMethodReleaseData, 1);
13676         release_data->handle = handle;
13677         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13678         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13679                 g_free (release_data);
13680
13681         /* Fix up refs entries pointing at us */
13682         for (l = mb->referenced_by; l; l = l->next) {
13683                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13684                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13685                 gpointer *data;
13686                 
13687                 g_assert (method->mhandle);
13688
13689                 data = (gpointer*)wrapper->method_data;
13690                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13691                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13692                                 data [i + 1] = mb->mhandle;
13693                 }
13694         }
13695         g_slist_free (mb->referenced_by);
13696
13697         /* ilgen is no longer needed */
13698         mb->ilgen = NULL;
13699
13700         domain = mono_domain_get ();
13701         mono_domain_lock (domain);
13702         if (!domain->method_to_dyn_method)
13703                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13704         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13705         mono_domain_unlock (domain);
13706
13707         return TRUE;
13708 }
13709
13710 void
13711 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13712 {
13713         MonoError error;
13714         (void) reflection_create_dynamic_method (mb, &error);
13715         mono_error_set_pending_exception (&error);
13716 }
13717
13718 #endif /* DISABLE_REFLECTION_EMIT */
13719
13720 /**
13721  * 
13722  * mono_reflection_is_valid_dynamic_token:
13723  * 
13724  * Returns TRUE if token is valid.
13725  * 
13726  */
13727 gboolean
13728 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13729 {
13730         return lookup_dyn_token (image, token) != NULL;
13731 }
13732
13733 MonoMethodSignature *
13734 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13735 {
13736         MonoMethodSignature *sig;
13737         g_assert (image_is_dynamic (image));
13738
13739         mono_error_init (error);
13740
13741         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13742         if (sig)
13743                 return sig;
13744
13745         return mono_method_signature_checked (method, error);
13746 }
13747
13748 #ifndef DISABLE_REFLECTION_EMIT
13749
13750 /**
13751  * mono_reflection_lookup_dynamic_token:
13752  *
13753  * Finish the Builder object pointed to by TOKEN and return the corresponding
13754  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13755  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13756  * mapping table.
13757  *
13758  * LOCKING: Take the loader lock
13759  */
13760 gpointer
13761 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13762 {
13763         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13764         MonoObject *obj;
13765         MonoClass *klass;
13766
13767         mono_error_init (error);
13768         
13769         obj = lookup_dyn_token (assembly, token);
13770         if (!obj) {
13771                 if (valid_token)
13772                         g_error ("Could not find required dynamic token 0x%08x", token);
13773                 else {
13774                         mono_error_set_execution_engine (error, "Could not find dynamic token 0x%08x", token);
13775                         return NULL;
13776                 }
13777         }
13778
13779         if (!handle_class)
13780                 handle_class = &klass;
13781         gpointer result = resolve_object (image, obj, handle_class, context, error);
13782         return result;
13783 }
13784
13785 /*
13786  * ensure_complete_type:
13787  *
13788  *   Ensure that KLASS is completed if it is a dynamic type, or references
13789  * dynamic types.
13790  */
13791 static void
13792 ensure_complete_type (MonoClass *klass, MonoError *error)
13793 {
13794         mono_error_init (error);
13795
13796         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13797                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13798
13799                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13800                 return_if_nok (error);
13801
13802                 // Asserting here could break a lot of code
13803                 //g_assert (klass->wastypebuilder);
13804         }
13805
13806         if (klass->generic_class) {
13807                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13808                 int i;
13809
13810                 for (i = 0; i < inst->type_argc; ++i) {
13811                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13812                         return_if_nok (error);
13813                 }
13814         }
13815 }
13816
13817 static gpointer
13818 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13819 {
13820         gpointer result = NULL;
13821
13822         mono_error_init (error);
13823
13824         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13825                 result = mono_string_intern_checked ((MonoString*)obj, error);
13826                 return_val_if_nok (error, NULL);
13827                 *handle_class = mono_defaults.string_class;
13828                 g_assert (result);
13829         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13830                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13831                 return_val_if_nok (error, NULL);
13832                 MonoClass *mc = mono_class_from_mono_type (type);
13833                 if (!mono_class_init (mc)) {
13834                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13835                         return NULL;
13836                 }
13837
13838                 if (context) {
13839                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13840                         return_val_if_nok (error, NULL);
13841
13842                         result = mono_class_from_mono_type (inflated);
13843                         mono_metadata_free_type (inflated);
13844                 } else {
13845                         result = mono_class_from_mono_type (type);
13846                 }
13847                 *handle_class = mono_defaults.typehandle_class;
13848                 g_assert (result);
13849         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13850                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13851                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13852                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13853                 result = ((MonoReflectionMethod*)obj)->method;
13854                 if (context) {
13855                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13856                         mono_error_assert_ok (error);
13857                 }
13858                 *handle_class = mono_defaults.methodhandle_class;
13859                 g_assert (result);
13860         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13861                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13862                 result = mb->mhandle;
13863                 if (!result) {
13864                         /* Type is not yet created */
13865                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13866
13867                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13868                         return_val_if_nok (error, NULL);
13869
13870                         /*
13871                          * Hopefully this has been filled in by calling CreateType() on the
13872                          * TypeBuilder.
13873                          */
13874                         /*
13875                          * TODO: This won't work if the application finishes another 
13876                          * TypeBuilder instance instead of this one.
13877                          */
13878                         result = mb->mhandle;
13879                 }
13880                 if (context) {
13881                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13882                         mono_error_assert_ok (error);
13883                 }
13884                 *handle_class = mono_defaults.methodhandle_class;
13885         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13886                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13887
13888                 result = cb->mhandle;
13889                 if (!result) {
13890                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13891
13892                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13893                         return_val_if_nok (error, NULL);
13894                         result = cb->mhandle;
13895                 }
13896                 if (context) {
13897                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13898                         mono_error_assert_ok (error);
13899                 }
13900                 *handle_class = mono_defaults.methodhandle_class;
13901         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13902                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13903
13904                 ensure_complete_type (field->parent, error);
13905                 return_val_if_nok (error, NULL);
13906
13907                 if (context) {
13908                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13909                         return_val_if_nok (error, NULL);
13910
13911                         MonoClass *klass = mono_class_from_mono_type (inflated);
13912                         MonoClassField *inflated_field;
13913                         gpointer iter = NULL;
13914                         mono_metadata_free_type (inflated);
13915                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13916                                 if (!strcmp (field->name, inflated_field->name))
13917                                         break;
13918                         }
13919                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13920                         result = inflated_field;
13921                 } else {
13922                         result = field;
13923                 }
13924                 *handle_class = mono_defaults.fieldhandle_class;
13925                 g_assert (result);
13926         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13927                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13928                 result = fb->handle;
13929
13930                 if (!result) {
13931                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13932
13933                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13934                         return_val_if_nok (error, NULL);
13935                         result = fb->handle;
13936                 }
13937
13938                 if (fb->handle && fb->handle->parent->generic_container) {
13939                         MonoClass *klass = fb->handle->parent;
13940                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13941                         return_val_if_nok (error, NULL);
13942
13943                         MonoClass *inflated = mono_class_from_mono_type (type);
13944
13945                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13946                         g_assert (result);
13947                         mono_metadata_free_type (type);
13948                 }
13949                 *handle_class = mono_defaults.fieldhandle_class;
13950         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13951                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13952                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13953                 return_val_if_nok (error, NULL);
13954                 MonoClass *klass;
13955
13956                 klass = type->data.klass;
13957                 if (klass->wastypebuilder) {
13958                         /* Already created */
13959                         result = klass;
13960                 }
13961                 else {
13962                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13963                         return_val_if_nok (error, NULL);
13964                         result = type->data.klass;
13965                         g_assert (result);
13966                 }
13967                 *handle_class = mono_defaults.typehandle_class;
13968         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13969                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13970                 MonoMethodSignature *sig;
13971                 int nargs, i;
13972
13973                 if (helper->arguments)
13974                         nargs = mono_array_length (helper->arguments);
13975                 else
13976                         nargs = 0;
13977
13978                 sig = mono_metadata_signature_alloc (image, nargs);
13979                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13980                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13981
13982                 if (helper->unmanaged_call_conv) { /* unmanaged */
13983                         sig->call_convention = helper->unmanaged_call_conv - 1;
13984                         sig->pinvoke = TRUE;
13985                 } else if (helper->call_conv & 0x02) {
13986                         sig->call_convention = MONO_CALL_VARARG;
13987                 } else {
13988                         sig->call_convention = MONO_CALL_DEFAULT;
13989                 }
13990
13991                 sig->param_count = nargs;
13992                 /* TODO: Copy type ? */
13993                 sig->ret = helper->return_type->type;
13994                 for (i = 0; i < nargs; ++i) {
13995                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13996                         if (!is_ok (error)) {
13997                                 image_g_free (image, sig);
13998                                 return NULL;
13999                         }
14000                 }
14001
14002                 result = sig;
14003                 *handle_class = NULL;
14004         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
14005                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
14006                 /* Already created by the managed code */
14007                 g_assert (method->mhandle);
14008                 result = method->mhandle;
14009                 *handle_class = mono_defaults.methodhandle_class;
14010         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
14011                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14012                 return_val_if_nok (error, NULL);
14013                 type = mono_class_inflate_generic_type_checked (type, context, error);
14014                 return_val_if_nok (error, NULL);
14015
14016                 result = mono_class_from_mono_type (type);
14017                 *handle_class = mono_defaults.typehandle_class;
14018                 g_assert (result);
14019                 mono_metadata_free_type (type);
14020         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
14021                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
14022                 return_val_if_nok (error, NULL);
14023                 type = mono_class_inflate_generic_type_checked (type, context, error);
14024                 return_val_if_nok (error, NULL);
14025
14026                 result = mono_class_from_mono_type (type);
14027                 *handle_class = mono_defaults.typehandle_class;
14028                 g_assert (result);
14029                 mono_metadata_free_type (type);
14030         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
14031                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
14032                 MonoClass *inflated;
14033                 MonoType *type;
14034                 MonoClassField *field;
14035
14036                 if (is_sre_field_builder (mono_object_class (f->fb)))
14037                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
14038                 else if (is_sr_mono_field (mono_object_class (f->fb)))
14039                         field = ((MonoReflectionField*)f->fb)->field;
14040                 else
14041                         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)));
14042
14043                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
14044                 return_val_if_nok (error, NULL);
14045                 type = mono_class_inflate_generic_type_checked (finst, context, error);
14046                 return_val_if_nok (error, NULL);
14047
14048                 inflated = mono_class_from_mono_type (type);
14049
14050                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
14051                 ensure_complete_type (field->parent, error);
14052                 if (!is_ok (error)) {
14053                         mono_metadata_free_type (type);
14054                         return NULL;
14055                 }
14056
14057                 g_assert (result);
14058                 mono_metadata_free_type (type);
14059                 *handle_class = mono_defaults.fieldhandle_class;
14060         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
14061                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
14062                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
14063                 return_val_if_nok (error, NULL);
14064                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
14065                 return_val_if_nok (error, NULL);
14066
14067                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
14068                 MonoMethod *method;
14069
14070                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14071                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14072                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14073                         method = ((MonoReflectionMethod *)c->cb)->method;
14074                 else
14075                         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)));
14076
14077                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14078                 *handle_class = mono_defaults.methodhandle_class;
14079                 mono_metadata_free_type (type);
14080         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14081                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14082                 if (m->method_args) {
14083                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14084                         return_val_if_nok (error, NULL);
14085                         if (context) {
14086                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14087                                 mono_error_assert_ok (error);
14088                         }
14089                 } else {
14090                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14091                         return_val_if_nok (error, NULL);
14092                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14093                         return_val_if_nok (error, NULL);
14094
14095                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14096                         MonoMethod *method;
14097
14098                         if (is_sre_method_builder (mono_object_class (m->mb)))
14099                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14100                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14101                                 method = ((MonoReflectionMethod *)m->mb)->method;
14102                         else
14103                                 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)));
14104
14105                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14106                         mono_metadata_free_type (type);
14107                 }
14108                 *handle_class = mono_defaults.methodhandle_class;
14109         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14110                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14111                 MonoType *mtype;
14112                 MonoClass *klass;
14113                 MonoMethod *method;
14114                 gpointer iter;
14115                 char *name;
14116
14117                 mtype = mono_reflection_type_get_handle (m->parent, error);
14118                 return_val_if_nok (error, NULL);
14119                 klass = mono_class_from_mono_type (mtype);
14120
14121                 /* Find the method */
14122
14123                 name = mono_string_to_utf8 (m->name);
14124                 iter = NULL;
14125                 while ((method = mono_class_get_methods (klass, &iter))) {
14126                         if (!strcmp (method->name, name))
14127                                 break;
14128                 }
14129                 g_free (name);
14130
14131                 // FIXME:
14132                 g_assert (method);
14133                 // FIXME: Check parameters/return value etc. match
14134
14135                 result = method;
14136                 *handle_class = mono_defaults.methodhandle_class;
14137         } else if (is_sre_array (mono_object_get_class(obj)) ||
14138                                 is_sre_byref (mono_object_get_class(obj)) ||
14139                                 is_sre_pointer (mono_object_get_class(obj))) {
14140                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14141                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14142                 return_val_if_nok (error, NULL);
14143
14144                 if (context) {
14145                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14146                         return_val_if_nok (error, NULL);
14147
14148                         result = mono_class_from_mono_type (inflated);
14149                         mono_metadata_free_type (inflated);
14150                 } else {
14151                         result = mono_class_from_mono_type (type);
14152                 }
14153                 *handle_class = mono_defaults.typehandle_class;
14154         } else {
14155                 g_print ("%s\n", obj->vtable->klass->name);
14156                 g_assert_not_reached ();
14157         }
14158         return result;
14159 }
14160
14161 #else /* DISABLE_REFLECTION_EMIT */
14162
14163 MonoArray*
14164 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14165 {
14166         g_assert_not_reached ();
14167         return NULL;
14168 }
14169
14170 void
14171 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14172 {
14173         g_assert_not_reached ();
14174 }
14175
14176 void
14177 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14178 {
14179         g_assert_not_reached ();
14180 }
14181
14182 gboolean
14183 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb, MonoError *error)
14184 {
14185         g_assert_not_reached ();
14186         return FALSE;
14187 }
14188
14189 void
14190 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14191 {
14192         g_assert_not_reached ();
14193 }
14194
14195 void
14196 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14197 {
14198         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14199 }
14200
14201 void
14202 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14203 {
14204         g_assert_not_reached ();
14205 }
14206
14207 void
14208 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14209 {
14210         g_assert_not_reached ();
14211 }
14212
14213 MonoReflectionModule *
14214 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14215 {
14216         g_assert_not_reached ();
14217         return NULL;
14218 }
14219
14220 guint32
14221 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14222 {
14223         g_assert_not_reached ();
14224         return 0;
14225 }
14226
14227 guint32
14228 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14229 {
14230         g_assert_not_reached ();
14231         return 0;
14232 }
14233
14234 guint32
14235 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14236                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14237 {
14238         g_assert_not_reached ();
14239         return 0;
14240 }
14241
14242 void
14243 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14244 {
14245 }
14246
14247 void
14248 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14249 {
14250         g_assert_not_reached ();
14251 }
14252
14253 void
14254 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14255 {
14256         mono_error_init (error);
14257         *overrides = NULL;
14258         *num_overrides = 0;
14259 }
14260
14261 MonoReflectionEvent *
14262 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14263 {
14264         g_assert_not_reached ();
14265         return NULL;
14266 }
14267
14268 MonoReflectionType*
14269 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14270 {
14271         g_assert_not_reached ();
14272         return NULL;
14273 }
14274
14275 void
14276 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14277 {
14278         g_assert_not_reached ();
14279 }
14280
14281 MonoArray *
14282 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14283 {
14284         g_assert_not_reached ();
14285         return NULL;
14286 }
14287
14288 MonoArray *
14289 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14290 {
14291         g_assert_not_reached ();
14292         return NULL;
14293 }
14294
14295 void 
14296 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14297 {
14298 }
14299
14300 gpointer
14301 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14302 {
14303         return NULL;
14304 }
14305
14306 MonoType*
14307 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14308 {
14309         mono_error_init (error);
14310         if (!ref)
14311                 return NULL;
14312         return ref->type;
14313 }
14314
14315 void
14316 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14317 {
14318         g_assert_not_reached ();
14319 }
14320
14321 #endif /* DISABLE_REFLECTION_EMIT */
14322
14323 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14324 const static guint32 declsec_flags_map[] = {
14325         0x00000000,                                     /* empty */
14326         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14327         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14328         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14329         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14330         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14331         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14332         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14333         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14334         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14335         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14336         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14337         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14338         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14339         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14340         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14341         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14342         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14343         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14344 };
14345
14346 /*
14347  * Returns flags that includes all available security action associated to the handle.
14348  * @token: metadata token (either for a class or a method)
14349  * @image: image where resides the metadata.
14350  */
14351 static guint32
14352 mono_declsec_get_flags (MonoImage *image, guint32 token)
14353 {
14354         int index = mono_metadata_declsec_from_index (image, token);
14355         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14356         guint32 result = 0;
14357         guint32 action;
14358         int i;
14359
14360         /* HasSecurity can be present for other, not specially encoded, attributes,
14361            e.g. SuppressUnmanagedCodeSecurityAttribute */
14362         if (index < 0)
14363                 return 0;
14364
14365         for (i = index; i < t->rows; i++) {
14366                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14367
14368                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14369                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14370                         break;
14371
14372                 action = cols [MONO_DECL_SECURITY_ACTION];
14373                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14374                         result |= declsec_flags_map [action];
14375                 } else {
14376                         g_assert_not_reached ();
14377                 }
14378         }
14379         return result;
14380 }
14381
14382 /*
14383  * Get the security actions (in the form of flags) associated with the specified method.
14384  *
14385  * @method: The method for which we want the declarative security flags.
14386  * Return the declarative security flags for the method (only).
14387  *
14388  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14389  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14390  */
14391 guint32
14392 mono_declsec_flags_from_method (MonoMethod *method)
14393 {
14394         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14395                 /* FIXME: No cache (for the moment) */
14396                 guint32 idx = mono_method_get_index (method);
14397                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14398                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14399                 return mono_declsec_get_flags (method->klass->image, idx);
14400         }
14401         return 0;
14402 }
14403
14404 /*
14405  * Get the security actions (in the form of flags) associated with the specified class.
14406  *
14407  * @klass: The class for which we want the declarative security flags.
14408  * Return the declarative security flags for the class.
14409  *
14410  * Note: We cache the flags inside the MonoClass structure as this will get 
14411  *       called very often (at least for each method).
14412  */
14413 guint32
14414 mono_declsec_flags_from_class (MonoClass *klass)
14415 {
14416         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14417                 if (!klass->ext || !klass->ext->declsec_flags) {
14418                         guint32 idx;
14419
14420                         idx = mono_metadata_token_index (klass->type_token);
14421                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14422                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14423                         mono_loader_lock ();
14424                         mono_class_alloc_ext (klass);
14425                         mono_loader_unlock ();
14426                         /* we cache the flags on classes */
14427                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14428                 }
14429                 return klass->ext->declsec_flags;
14430         }
14431         return 0;
14432 }
14433
14434 /*
14435  * Get the security actions (in the form of flags) associated with the specified assembly.
14436  *
14437  * @assembly: The assembly for which we want the declarative security flags.
14438  * Return the declarative security flags for the assembly.
14439  */
14440 guint32
14441 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14442 {
14443         guint32 idx = 1; /* there is only one assembly */
14444         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14445         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14446         return mono_declsec_get_flags (assembly->image, idx);
14447 }
14448
14449
14450 /*
14451  * Fill actions for the specific index (which may either be an encoded class token or
14452  * an encoded method token) from the metadata image.
14453  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14454  */
14455 static MonoBoolean
14456 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14457         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14458 {
14459         MonoBoolean result = FALSE;
14460         MonoTableInfo *t;
14461         guint32 cols [MONO_DECL_SECURITY_SIZE];
14462         int index = mono_metadata_declsec_from_index (image, token);
14463         int i;
14464
14465         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14466         for (i = index; i < t->rows; i++) {
14467                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14468
14469                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14470                         return result;
14471
14472                 /* if present only replace (class) permissions with method permissions */
14473                 /* if empty accept either class or method permissions */
14474                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14475                         if (!actions->demand.blob) {
14476                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14477                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14478                                 actions->demand.blob = (char*) (blob + 2);
14479                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14480                                 result = TRUE;
14481                         }
14482                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14483                         if (!actions->noncasdemand.blob) {
14484                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14485                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14486                                 actions->noncasdemand.blob = (char*) (blob + 2);
14487                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14488                                 result = TRUE;
14489                         }
14490                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14491                         if (!actions->demandchoice.blob) {
14492                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14493                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14494                                 actions->demandchoice.blob = (char*) (blob + 2);
14495                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14496                                 result = TRUE;
14497                         }
14498                 }
14499         }
14500
14501         return result;
14502 }
14503
14504 static MonoBoolean
14505 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14506         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14507 {
14508         guint32 idx = mono_metadata_token_index (klass->type_token);
14509         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14510         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14511         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14512 }
14513
14514 static MonoBoolean
14515 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14516         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14517 {
14518         guint32 idx = mono_method_get_index (method);
14519         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14520         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14521         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14522 }
14523
14524 /*
14525  * Collect all actions (that requires to generate code in mini) assigned for
14526  * the specified method.
14527  * Note: Don't use the content of actions if the function return FALSE.
14528  */
14529 MonoBoolean
14530 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14531 {
14532         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14533                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14534         MonoBoolean result = FALSE;
14535         guint32 flags;
14536
14537         /* quick exit if no declarative security is present in the metadata */
14538         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14539                 return FALSE;
14540
14541         /* we want the original as the wrapper is "free" of the security informations */
14542         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14543                 method = mono_marshal_method_from_wrapper (method);
14544                 if (!method)
14545                         return FALSE;
14546         }
14547
14548         /* First we look for method-level attributes */
14549         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14550                 mono_class_init (method->klass);
14551                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14552
14553                 result = mono_declsec_get_method_demands_params (method, demands, 
14554                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14555         }
14556
14557         /* Here we use (or create) the class declarative cache to look for demands */
14558         flags = mono_declsec_flags_from_class (method->klass);
14559         if (flags & mask) {
14560                 if (!result) {
14561                         mono_class_init (method->klass);
14562                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14563                 }
14564                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14565                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14566         }
14567
14568         /* The boolean return value is used as a shortcut in case nothing needs to
14569            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14570         return result;
14571 }
14572
14573
14574 /*
14575  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14576  *
14577  * Note: Don't use the content of actions if the function return FALSE.
14578  */
14579 MonoBoolean
14580 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14581 {
14582         MonoBoolean result = FALSE;
14583         guint32 flags;
14584
14585         /* quick exit if no declarative security is present in the metadata */
14586         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14587                 return FALSE;
14588
14589         /* we want the original as the wrapper is "free" of the security informations */
14590         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14591                 method = mono_marshal_method_from_wrapper (method);
14592                 if (!method)
14593                         return FALSE;
14594         }
14595
14596         /* results are independant - zeroize both */
14597         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14598         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14599
14600         /* First we look for method-level attributes */
14601         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14602                 mono_class_init (method->klass);
14603
14604                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14605                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14606         }
14607
14608         /* Here we use (or create) the class declarative cache to look for demands */
14609         flags = mono_declsec_flags_from_class (method->klass);
14610         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14611                 mono_class_init (method->klass);
14612
14613                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14614                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14615         }
14616
14617         return result;
14618 }
14619
14620 /*
14621  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14622  *
14623  * @klass       The inherited class - this is the class that provides the security check (attributes)
14624  * @demans      
14625  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14626  * 
14627  * Note: Don't use the content of actions if the function return FALSE.
14628  */
14629 MonoBoolean
14630 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14631 {
14632         MonoBoolean result = FALSE;
14633         guint32 flags;
14634
14635         /* quick exit if no declarative security is present in the metadata */
14636         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14637                 return FALSE;
14638
14639         /* Here we use (or create) the class declarative cache to look for demands */
14640         flags = mono_declsec_flags_from_class (klass);
14641         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14642                 mono_class_init (klass);
14643                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14644
14645                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14646                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14647         }
14648
14649         return result;
14650 }
14651
14652 /*
14653  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14654  *
14655  * Note: Don't use the content of actions if the function return FALSE.
14656  */
14657 MonoBoolean
14658 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14659 {
14660         /* quick exit if no declarative security is present in the metadata */
14661         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14662                 return FALSE;
14663
14664         /* we want the original as the wrapper is "free" of the security informations */
14665         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14666                 method = mono_marshal_method_from_wrapper (method);
14667                 if (!method)
14668                         return FALSE;
14669         }
14670
14671         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14672                 mono_class_init (method->klass);
14673                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14674
14675                 return mono_declsec_get_method_demands_params (method, demands, 
14676                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14677         }
14678         return FALSE;
14679 }
14680
14681
14682 static MonoBoolean
14683 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14684 {
14685         guint32 cols [MONO_DECL_SECURITY_SIZE];
14686         MonoTableInfo *t;
14687         int i;
14688
14689         int index = mono_metadata_declsec_from_index (image, token);
14690         if (index == -1)
14691                 return FALSE;
14692
14693         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14694         for (i = index; i < t->rows; i++) {
14695                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14696
14697                 /* shortcut - index are ordered */
14698                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14699                         return FALSE;
14700
14701                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14702                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14703                         entry->blob = (char*) (metadata + 2);
14704                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14705                         return TRUE;
14706                 }
14707         }
14708
14709         return FALSE;
14710 }
14711
14712 MonoBoolean
14713 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14714 {
14715         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14716                 guint32 idx = mono_method_get_index (method);
14717                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14718                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14719                 return get_declsec_action (method->klass->image, idx, action, entry);
14720         }
14721         return FALSE;
14722 }
14723
14724 MonoBoolean
14725 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14726 {
14727         /* use cache */
14728         guint32 flags = mono_declsec_flags_from_class (klass);
14729         if (declsec_flags_map [action] & flags) {
14730                 guint32 idx = mono_metadata_token_index (klass->type_token);
14731                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14732                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14733                 return get_declsec_action (klass->image, idx, action, entry);
14734         }
14735         return FALSE;
14736 }
14737
14738 MonoBoolean
14739 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14740 {
14741         guint32 idx = 1; /* there is only one assembly */
14742         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14743         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14744
14745         return get_declsec_action (assembly->image, idx, action, entry);
14746 }
14747
14748 gboolean
14749 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14750 {
14751         MonoObject *res, *exc;
14752         void *params [1];
14753         static MonoMethod *method = NULL;
14754
14755         mono_error_init (error);
14756
14757         if (method == NULL) {
14758                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14759                 g_assert (method);
14760         }
14761
14762         /* 
14763          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14764          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14765          */
14766         g_assert (mono_class_get_ref_info (klass));
14767         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14768
14769         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14770         return_val_if_nok (error, FALSE);
14771
14772         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14773
14774         if (exc || !mono_error_ok (error)) {
14775                 mono_error_cleanup (error);
14776                 return FALSE;
14777         } else
14778                 return *(MonoBoolean*)mono_object_unbox (res);
14779 }
14780
14781 /**
14782  * mono_reflection_type_get_type:
14783  * @reftype: the System.Type object
14784  *
14785  * Returns the MonoType* associated with the C# System.Type object @reftype.
14786  */
14787 MonoType*
14788 mono_reflection_type_get_type (MonoReflectionType *reftype)
14789 {
14790         g_assert (reftype);
14791
14792         MonoError error;
14793         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14794         mono_error_assert_ok (&error);
14795         return result;
14796 }
14797
14798 /**
14799  * mono_reflection_assembly_get_assembly:
14800  * @refassembly: the System.Reflection.Assembly object
14801  *
14802  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14803  */
14804 MonoAssembly*
14805 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14806 {
14807         g_assert (refassembly);
14808
14809         return refassembly->assembly;
14810 }
14811