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