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