[runtime] Avoid setting klass->instance_size if its already set, this can happen...
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static gboolean type_is_reference (MonoType *type);
191
192 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
193 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
194 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
195
196 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
197 static void init_type_builder_generics (MonoObject *type);
198
199 #define RESOLVE_TYPE(type, error) do {                                  \
200         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
201 } while (0)
202 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
203         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
204         __type = mono_reflection_type_resolve_user_types (__type, error); \
205         if (mono_error_ok (error))                                      \
206                 mono_array_set (arr, MonoReflectionType*, index, __type); \
207 } while (0)
208
209 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
210
211 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
212 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
213
214 #if SIZEOF_VOID_P == 4
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
216 #else
217 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
218 #endif
219
220 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
221 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
222
223 /* Class lazy loading functions */
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
232 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
233 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
234 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
235 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
236 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
237 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
238 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
239 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
240 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
241 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
242 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
243
244 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
245 static GPtrArray *dynamic_images;
246 static mono_mutex_t dynamic_images_mutex;
247
248 static inline void
249 dynamic_images_lock (void)
250 {
251         mono_os_mutex_lock (&dynamic_images_mutex);
252 }
253
254 static inline void
255 dynamic_images_unlock (void)
256 {
257         mono_os_mutex_unlock (&dynamic_images_mutex);
258 }
259
260 /**
261  * mono_find_dynamic_image_owner:
262  *
263  * Find the dynamic image, if any, which a given pointer is located in the memory of.
264  */
265 MonoImage *
266 mono_find_dynamic_image_owner (void *ptr)
267 {
268         MonoImage *owner = NULL;
269         int i;
270
271         dynamic_images_lock ();
272
273         if (dynamic_images)
274         {
275                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
276                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
277                         if (mono_mempool_contains_addr (image->mempool, ptr))
278                                 owner = image;
279                 }
280         }
281
282         dynamic_images_unlock ();
283
284         return owner;
285 }
286
287 void
288 mono_reflection_init (void)
289 {
290         mono_os_mutex_init (&dynamic_images_mutex);
291 }
292
293 static inline void
294 dynamic_image_lock (MonoDynamicImage *image)
295 {
296         MONO_PREPARE_BLOCKING;
297         mono_image_lock ((MonoImage*)image);
298         MONO_FINISH_BLOCKING;
299 }
300
301 static inline void
302 dynamic_image_unlock (MonoDynamicImage *image)
303 {
304         mono_image_unlock ((MonoImage*)image);
305 }
306
307 static void
308 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
309 {
310         MONO_REQ_GC_UNSAFE_MODE;
311
312         dynamic_image_lock (assembly);
313         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
314         dynamic_image_unlock (assembly);
315 }
316
317 static MonoObject*
318 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
319 {
320         MONO_REQ_GC_UNSAFE_MODE;
321
322         MonoObject *obj;
323
324         dynamic_image_lock (assembly);
325         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
326         dynamic_image_unlock (assembly);
327
328         return obj;
329 }
330
331 static void
332 sigbuffer_init (SigBuffer *buf, int size)
333 {
334         MONO_REQ_GC_NEUTRAL_MODE;
335
336         buf->buf = (char *)g_malloc (size);
337         buf->p = buf->buf;
338         buf->end = buf->buf + size;
339 }
340
341 static void
342 sigbuffer_make_room (SigBuffer *buf, int size)
343 {
344         MONO_REQ_GC_NEUTRAL_MODE;
345
346         if (buf->end - buf->p < size) {
347                 int new_size = buf->end - buf->buf + size + 32;
348                 char *p = (char *)g_realloc (buf->buf, new_size);
349                 size = buf->p - buf->buf;
350                 buf->buf = p;
351                 buf->p = p + size;
352                 buf->end = buf->buf + new_size;
353         }
354 }
355
356 static void
357 sigbuffer_add_value (SigBuffer *buf, guint32 val)
358 {
359         MONO_REQ_GC_NEUTRAL_MODE;
360
361         sigbuffer_make_room (buf, 6);
362         mono_metadata_encode_value (val, buf->p, &buf->p);
363 }
364
365 static void
366 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
367 {
368         MONO_REQ_GC_NEUTRAL_MODE;
369
370         sigbuffer_make_room (buf, 1);
371         buf->p [0] = val;
372         buf->p++;
373 }
374
375 static void
376 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
377 {
378         MONO_REQ_GC_NEUTRAL_MODE;
379
380         sigbuffer_make_room (buf, size);
381         memcpy (buf->p, p, size);
382         buf->p += size;
383 }
384
385 static void
386 sigbuffer_free (SigBuffer *buf)
387 {
388         MONO_REQ_GC_NEUTRAL_MODE;
389
390         g_free (buf->buf);
391 }
392
393 #ifndef DISABLE_REFLECTION_EMIT
394 /**
395  * mp_g_alloc:
396  *
397  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
398  * from the C heap.
399  */
400 static gpointer
401 image_g_malloc (MonoImage *image, guint size)
402 {
403         MONO_REQ_GC_NEUTRAL_MODE;
404
405         if (image)
406                 return mono_image_alloc (image, size);
407         else
408                 return g_malloc (size);
409 }
410 #endif /* !DISABLE_REFLECTION_EMIT */
411
412 /**
413  * image_g_alloc0:
414  *
415  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
416  * from the C heap.
417  */
418 static gpointer
419 image_g_malloc0 (MonoImage *image, guint size)
420 {
421         MONO_REQ_GC_NEUTRAL_MODE;
422
423         if (image)
424                 return mono_image_alloc0 (image, size);
425         else
426                 return g_malloc0 (size);
427 }
428
429 /**
430  * image_g_free:
431  * @image: a MonoImage
432  * @ptr: pointer
433  *
434  * If @image is NULL, free @ptr, otherwise do nothing.
435  */
436 static void
437 image_g_free (MonoImage *image, gpointer ptr)
438 {
439         if (image == NULL)
440                 g_free (ptr);
441 }
442
443 #ifndef DISABLE_REFLECTION_EMIT
444 static char*
445 image_strdup (MonoImage *image, const char *s)
446 {
447         MONO_REQ_GC_NEUTRAL_MODE;
448
449         if (image)
450                 return mono_image_strdup (image, s);
451         else
452                 return g_strdup (s);
453 }
454 #endif
455
456 #define image_g_new(image,struct_type, n_structs)               \
457     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
458
459 #define image_g_new0(image,struct_type, n_structs)              \
460     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
461
462
463 static void
464 alloc_table (MonoDynamicTable *table, guint nrows)
465 {
466         MONO_REQ_GC_NEUTRAL_MODE;
467
468         table->rows = nrows;
469         g_assert (table->columns);
470         if (nrows + 1 >= table->alloc_rows) {
471                 while (nrows + 1 >= table->alloc_rows) {
472                         if (table->alloc_rows == 0)
473                                 table->alloc_rows = 16;
474                         else
475                                 table->alloc_rows *= 2;
476                 }
477
478                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
479         }
480 }
481
482 static void
483 make_room_in_stream (MonoDynamicStream *stream, int size)
484 {
485         MONO_REQ_GC_NEUTRAL_MODE;
486
487         if (size <= stream->alloc_size)
488                 return;
489         
490         while (stream->alloc_size <= size) {
491                 if (stream->alloc_size < 4096)
492                         stream->alloc_size = 4096;
493                 else
494                         stream->alloc_size *= 2;
495         }
496         
497         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
498 }
499
500 static guint32
501 string_heap_insert (MonoDynamicStream *sh, const char *str)
502 {
503         MONO_REQ_GC_NEUTRAL_MODE;
504
505         guint32 idx;
506         guint32 len;
507         gpointer oldkey, oldval;
508
509         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
510                 return GPOINTER_TO_UINT (oldval);
511
512         len = strlen (str) + 1;
513         idx = sh->index;
514         
515         make_room_in_stream (sh, idx + len);
516
517         /*
518          * We strdup the string even if we already copy them in sh->data
519          * so that the string pointers in the hash remain valid even if
520          * we need to realloc sh->data. We may want to avoid that later.
521          */
522         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
523         memcpy (sh->data + idx, str, len);
524         sh->index += len;
525         return idx;
526 }
527
528 static guint32
529 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
530 {
531         MONO_REQ_GC_UNSAFE_MODE;
532
533         char *name = mono_string_to_utf8 (str);
534         guint32 idx;
535         idx = string_heap_insert (sh, name);
536         g_free (name);
537         return idx;
538 }
539
540 #ifndef DISABLE_REFLECTION_EMIT
541 static void
542 string_heap_init (MonoDynamicStream *sh)
543 {
544         MONO_REQ_GC_NEUTRAL_MODE;
545
546         sh->index = 0;
547         sh->alloc_size = 4096;
548         sh->data = (char *)g_malloc (4096);
549         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
550         string_heap_insert (sh, "");
551 }
552 #endif
553
554 static guint32
555 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
556 {
557         MONO_REQ_GC_NEUTRAL_MODE;
558
559         guint32 idx;
560         
561         make_room_in_stream (stream, stream->index + len);
562         memcpy (stream->data + stream->index, data, len);
563         idx = stream->index;
564         stream->index += len;
565         /* 
566          * align index? Not without adding an additional param that controls it since
567          * we may store a blob value in pieces.
568          */
569         return idx;
570 }
571
572 static guint32
573 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
574 {
575         MONO_REQ_GC_NEUTRAL_MODE;
576
577         guint32 idx;
578         
579         make_room_in_stream (stream, stream->index + len);
580         memset (stream->data + stream->index, 0, len);
581         idx = stream->index;
582         stream->index += len;
583         return idx;
584 }
585
586 static void
587 stream_data_align (MonoDynamicStream *stream)
588 {
589         MONO_REQ_GC_NEUTRAL_MODE;
590
591         char buf [4] = {0};
592         guint32 count = stream->index % 4;
593
594         /* we assume the stream data will be aligned */
595         if (count)
596                 mono_image_add_stream_data (stream, buf, 4 - count);
597 }
598
599 #ifndef DISABLE_REFLECTION_EMIT
600 static int
601 mono_blob_entry_hash (const char* str)
602 {
603         MONO_REQ_GC_NEUTRAL_MODE;
604
605         guint len, h;
606         const char *end;
607         len = mono_metadata_decode_blob_size (str, &str);
608         if (len > 0) {
609                 end = str + len;
610                 h = *str;
611                 for (str += 1; str < end; str++)
612                         h = (h << 5) - h + *str;
613                 return h;
614         } else {
615                 return 0;
616         }
617 }
618
619 static gboolean
620 mono_blob_entry_equal (const char *str1, const char *str2) {
621         MONO_REQ_GC_NEUTRAL_MODE;
622
623         int len, len2;
624         const char *end1;
625         const char *end2;
626         len = mono_metadata_decode_blob_size (str1, &end1);
627         len2 = mono_metadata_decode_blob_size (str2, &end2);
628         if (len != len2)
629                 return 0;
630         return memcmp (end1, end2, len) == 0;
631 }
632 #endif
633 static guint32
634 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
635 {
636         MONO_REQ_GC_NEUTRAL_MODE;
637
638         guint32 idx;
639         char *copy;
640         gpointer oldkey, oldval;
641
642         copy = (char *)g_malloc (s1+s2);
643         memcpy (copy, b1, s1);
644         memcpy (copy + s1, b2, s2);
645         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
646                 g_free (copy);
647                 idx = GPOINTER_TO_UINT (oldval);
648         } else {
649                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
650                 mono_image_add_stream_data (&assembly->blob, b2, s2);
651                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
652         }
653         return idx;
654 }
655
656 static guint32
657 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
658 {
659         MONO_REQ_GC_NEUTRAL_MODE;
660
661         char blob_size [8];
662         char *b = blob_size;
663         guint32 size = buf->p - buf->buf;
664         /* store length */
665         g_assert (size <= (buf->end - buf->buf));
666         mono_metadata_encode_value (size, b, &b);
667         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
668 }
669
670 /*
671  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
672  * dest may be misaligned.
673  */
674 static void
675 swap_with_size (char *dest, const char* val, int len, int nelem) {
676         MONO_REQ_GC_NEUTRAL_MODE;
677 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
678         int elem;
679
680         for (elem = 0; elem < nelem; ++elem) {
681                 switch (len) {
682                 case 1:
683                         *dest = *val;
684                         break;
685                 case 2:
686                         dest [0] = val [1];
687                         dest [1] = val [0];
688                         break;
689                 case 4:
690                         dest [0] = val [3];
691                         dest [1] = val [2];
692                         dest [2] = val [1];
693                         dest [3] = val [0];
694                         break;
695                 case 8:
696                         dest [0] = val [7];
697                         dest [1] = val [6];
698                         dest [2] = val [5];
699                         dest [3] = val [4];
700                         dest [4] = val [3];
701                         dest [5] = val [2];
702                         dest [6] = val [1];
703                         dest [7] = val [0];
704                         break;
705                 default:
706                         g_assert_not_reached ();
707                 }
708                 dest += len;
709                 val += len;
710         }
711 #else
712         memcpy (dest, val, len * nelem);
713 #endif
714 }
715
716 static guint32
717 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
718 {
719         MONO_REQ_GC_UNSAFE_MODE;
720         
721         char blob_size [64];
722         char *b = blob_size;
723         guint32 idx = 0, len;
724
725         len = str->length * 2;
726         mono_metadata_encode_value (len, b, &b);
727 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
728         {
729                 char *swapped = g_malloc (2 * mono_string_length (str));
730                 const char *p = (const char*)mono_string_chars (str);
731
732                 swap_with_size (swapped, p, 2, mono_string_length (str));
733                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
734                 g_free (swapped);
735         }
736 #else
737         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
738 #endif
739         return idx;
740 }
741
742 #ifndef DISABLE_REFLECTION_EMIT
743 static MonoClass *
744 default_class_from_mono_type (MonoType *type)
745 {
746         MONO_REQ_GC_NEUTRAL_MODE;
747
748         switch (type->type) {
749         case MONO_TYPE_OBJECT:
750                 return mono_defaults.object_class;
751         case MONO_TYPE_VOID:
752                 return mono_defaults.void_class;
753         case MONO_TYPE_BOOLEAN:
754                 return mono_defaults.boolean_class;
755         case MONO_TYPE_CHAR:
756                 return mono_defaults.char_class;
757         case MONO_TYPE_I1:
758                 return mono_defaults.sbyte_class;
759         case MONO_TYPE_U1:
760                 return mono_defaults.byte_class;
761         case MONO_TYPE_I2:
762                 return mono_defaults.int16_class;
763         case MONO_TYPE_U2:
764                 return mono_defaults.uint16_class;
765         case MONO_TYPE_I4:
766                 return mono_defaults.int32_class;
767         case MONO_TYPE_U4:
768                 return mono_defaults.uint32_class;
769         case MONO_TYPE_I:
770                 return mono_defaults.int_class;
771         case MONO_TYPE_U:
772                 return mono_defaults.uint_class;
773         case MONO_TYPE_I8:
774                 return mono_defaults.int64_class;
775         case MONO_TYPE_U8:
776                 return mono_defaults.uint64_class;
777         case MONO_TYPE_R4:
778                 return mono_defaults.single_class;
779         case MONO_TYPE_R8:
780                 return mono_defaults.double_class;
781         case MONO_TYPE_STRING:
782                 return mono_defaults.string_class;
783         default:
784                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
785                 g_assert_not_reached ();
786         }
787         
788         return NULL;
789 }
790 #endif
791
792 /*
793  * mono_class_get_ref_info:
794  *
795  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
796  */
797 gpointer
798 mono_class_get_ref_info (MonoClass *klass)
799 {
800         MONO_REQ_GC_UNSAFE_MODE;
801
802         if (klass->ref_info_handle == 0)
803                 return NULL;
804         else
805                 return mono_gchandle_get_target (klass->ref_info_handle);
806 }
807
808 void
809 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
810 {
811         MONO_REQ_GC_UNSAFE_MODE;
812
813         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
814         g_assert (klass->ref_info_handle != 0);
815 }
816
817 void
818 mono_class_free_ref_info (MonoClass *klass)
819 {
820         MONO_REQ_GC_NEUTRAL_MODE;
821
822         if (klass->ref_info_handle) {
823                 mono_gchandle_free (klass->ref_info_handle);
824                 klass->ref_info_handle = 0;
825         }
826 }
827
828 static void
829 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
830 {
831         MONO_REQ_GC_NEUTRAL_MODE;
832
833         int i;
834         MonoGenericInst *class_inst;
835         MonoClass *klass;
836
837         g_assert (gclass);
838
839         class_inst = gclass->context.class_inst;
840
841         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
842         klass = gclass->container_class;
843         sigbuffer_add_value (buf, klass->byval_arg.type);
844         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
845
846         sigbuffer_add_value (buf, class_inst->type_argc);
847         for (i = 0; i < class_inst->type_argc; ++i)
848                 encode_type (assembly, class_inst->type_argv [i], buf);
849
850 }
851
852 static void
853 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
854 {
855         MONO_REQ_GC_NEUTRAL_MODE;
856
857         if (!type) {
858                 g_assert_not_reached ();
859                 return;
860         }
861                 
862         if (type->byref)
863                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
864
865         switch (type->type){
866         case MONO_TYPE_VOID:
867         case MONO_TYPE_BOOLEAN:
868         case MONO_TYPE_CHAR:
869         case MONO_TYPE_I1:
870         case MONO_TYPE_U1:
871         case MONO_TYPE_I2:
872         case MONO_TYPE_U2:
873         case MONO_TYPE_I4:
874         case MONO_TYPE_U4:
875         case MONO_TYPE_I8:
876         case MONO_TYPE_U8:
877         case MONO_TYPE_R4:
878         case MONO_TYPE_R8:
879         case MONO_TYPE_I:
880         case MONO_TYPE_U:
881         case MONO_TYPE_STRING:
882         case MONO_TYPE_OBJECT:
883         case MONO_TYPE_TYPEDBYREF:
884                 sigbuffer_add_value (buf, type->type);
885                 break;
886         case MONO_TYPE_PTR:
887                 sigbuffer_add_value (buf, type->type);
888                 encode_type (assembly, type->data.type, buf);
889                 break;
890         case MONO_TYPE_SZARRAY:
891                 sigbuffer_add_value (buf, type->type);
892                 encode_type (assembly, &type->data.klass->byval_arg, buf);
893                 break;
894         case MONO_TYPE_VALUETYPE:
895         case MONO_TYPE_CLASS: {
896                 MonoClass *k = mono_class_from_mono_type (type);
897
898                 if (k->generic_container) {
899                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
900                         encode_generic_class (assembly, gclass, buf);
901                 } else {
902                         /*
903                          * Make sure we use the correct type.
904                          */
905                         sigbuffer_add_value (buf, k->byval_arg.type);
906                         /*
907                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
908                          * otherwise two typerefs could point to the same type, leading to
909                          * verification errors.
910                          */
911                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
912                 }
913                 break;
914         }
915         case MONO_TYPE_ARRAY:
916                 sigbuffer_add_value (buf, type->type);
917                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
918                 sigbuffer_add_value (buf, type->data.array->rank);
919                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
920                 sigbuffer_add_value (buf, 0);
921                 break;
922         case MONO_TYPE_GENERICINST:
923                 encode_generic_class (assembly, type->data.generic_class, buf);
924                 break;
925         case MONO_TYPE_VAR:
926         case MONO_TYPE_MVAR:
927                 sigbuffer_add_value (buf, type->type);
928                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
929                 break;
930         default:
931                 g_error ("need to encode type %x", type->type);
932         }
933 }
934
935 static void
936 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
937 {
938         MONO_REQ_GC_UNSAFE_MODE;
939
940         mono_error_init (error);
941
942         if (!type) {
943                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
944                 return;
945         }
946
947         MonoType *t = mono_reflection_type_get_handle (type, error);
948         return_if_nok (error);
949         encode_type (assembly, t, buf);
950 }
951
952 static void
953 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
954 {
955         MONO_REQ_GC_UNSAFE_MODE;
956
957         int i;
958
959         mono_error_init (error);
960
961         if (modreq) {
962                 for (i = 0; i < mono_array_length (modreq); ++i) {
963                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
964                         return_if_nok (error);
965                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
966                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
967                 }
968         }
969         if (modopt) {
970                 for (i = 0; i < mono_array_length (modopt); ++i) {
971                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
972                         return_if_nok (error);
973                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
974                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
975                 }
976         }
977 }
978
979 #ifndef DISABLE_REFLECTION_EMIT
980 static guint32
981 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
982 {
983         MONO_REQ_GC_UNSAFE_MODE;
984
985         SigBuffer buf;
986         int i;
987         guint32 nparams =  sig->param_count;
988         guint32 idx;
989
990         if (!assembly->save)
991                 return 0;
992
993         sigbuffer_init (&buf, 32);
994         /*
995          * FIXME: vararg, explicit_this, differenc call_conv values...
996          */
997         idx = sig->call_convention;
998         if (sig->hasthis)
999                 idx |= 0x20; /* hasthis */
1000         if (sig->generic_param_count)
1001                 idx |= 0x10; /* generic */
1002         sigbuffer_add_byte (&buf, idx);
1003         if (sig->generic_param_count)
1004                 sigbuffer_add_value (&buf, sig->generic_param_count);
1005         sigbuffer_add_value (&buf, nparams);
1006         encode_type (assembly, sig->ret, &buf);
1007         for (i = 0; i < nparams; ++i) {
1008                 if (i == sig->sentinelpos)
1009                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1010                 encode_type (assembly, sig->params [i], &buf);
1011         }
1012         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1013         sigbuffer_free (&buf);
1014         return idx;
1015 }
1016 #endif
1017
1018 static guint32
1019 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1020 {
1021         MONO_REQ_GC_UNSAFE_MODE;
1022
1023         mono_error_init (error);
1024
1025         /*
1026          * FIXME: reuse code from method_encode_signature().
1027          */
1028         SigBuffer buf;
1029         int i;
1030         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1031         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1032         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1033         guint32 idx;
1034
1035         sigbuffer_init (&buf, 32);
1036         /* LAMESPEC: all the call conv spec is foobared */
1037         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1038         if (mb->call_conv & 2)
1039                 idx |= 0x5; /* vararg */
1040         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1041                 idx |= 0x20; /* hasthis */
1042         if (ngparams)
1043                 idx |= 0x10; /* generic */
1044         sigbuffer_add_byte (&buf, idx);
1045         if (ngparams)
1046                 sigbuffer_add_value (&buf, ngparams);
1047         sigbuffer_add_value (&buf, nparams + notypes);
1048         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1049         if (!is_ok (error))
1050                 goto leave;
1051         encode_reflection_type (assembly, mb->rtype, &buf, error);
1052         if (!is_ok (error))
1053                 goto leave;
1054         for (i = 0; i < nparams; ++i) {
1055                 MonoArray *modreq = NULL;
1056                 MonoArray *modopt = NULL;
1057                 MonoReflectionType *pt;
1058
1059                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1060                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1061                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1062                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1063                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1064                 if (!is_ok (error))
1065                         goto leave;
1066                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1067                 encode_reflection_type (assembly, pt, &buf, error);
1068                 if (!is_ok (error))
1069                         goto leave;
1070         }
1071         if (notypes)
1072                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1073         for (i = 0; i < notypes; ++i) {
1074                 MonoReflectionType *pt;
1075
1076                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1077                 encode_reflection_type (assembly, pt, &buf, error);
1078                 if (!is_ok (error))
1079                         goto leave;
1080         }
1081
1082         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1083 leave:
1084         sigbuffer_free (&buf);
1085         return idx;
1086 }
1087
1088 static guint32
1089 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1090 {
1091         MONO_REQ_GC_UNSAFE_MODE;
1092
1093         mono_error_init (error);
1094
1095         MonoDynamicTable *table;
1096         guint32 *values;
1097         guint32 idx, sig_idx;
1098         guint nl = mono_array_length (ilgen->locals);
1099         SigBuffer buf;
1100         int i;
1101
1102         sigbuffer_init (&buf, 32);
1103         sigbuffer_add_value (&buf, 0x07);
1104         sigbuffer_add_value (&buf, nl);
1105         for (i = 0; i < nl; ++i) {
1106                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1107                 
1108                 if (lb->is_pinned)
1109                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1110                 
1111                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1112                 if (!is_ok (error)) {
1113                         sigbuffer_free (&buf);
1114                         return 0;
1115                 }
1116         }
1117         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1118         sigbuffer_free (&buf);
1119
1120         if (assembly->standalonesig_cache == NULL)
1121                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1122         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1123         if (idx)
1124                 return idx;
1125
1126         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1127         idx = table->next_idx ++;
1128         table->rows ++;
1129         alloc_table (table, table->rows);
1130         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1131
1132         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1133
1134         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1135
1136         return idx;
1137 }
1138
1139 static guint32
1140 method_count_clauses (MonoReflectionILGen *ilgen)
1141 {
1142         MONO_REQ_GC_UNSAFE_MODE;
1143
1144         guint32 num_clauses = 0;
1145         int i;
1146
1147         MonoILExceptionInfo *ex_info;
1148         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1149                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1150                 if (ex_info->handlers)
1151                         num_clauses += mono_array_length (ex_info->handlers);
1152                 else
1153                         num_clauses++;
1154         }
1155
1156         return num_clauses;
1157 }
1158
1159 #ifndef DISABLE_REFLECTION_EMIT
1160 static MonoExceptionClause*
1161 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1162 {
1163         MONO_REQ_GC_UNSAFE_MODE;
1164
1165         mono_error_init (error);
1166
1167         MonoExceptionClause *clauses;
1168         MonoExceptionClause *clause;
1169         MonoILExceptionInfo *ex_info;
1170         MonoILExceptionBlock *ex_block;
1171         guint32 finally_start;
1172         int i, j, clause_index;;
1173
1174         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1175
1176         clause_index = 0;
1177         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1178                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1179                 finally_start = ex_info->start + ex_info->len;
1180                 if (!ex_info->handlers)
1181                         continue;
1182                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1183                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1184                         clause = &(clauses [clause_index]);
1185
1186                         clause->flags = ex_block->type;
1187                         clause->try_offset = ex_info->start;
1188
1189                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1190                                 clause->try_len = finally_start - ex_info->start;
1191                         else
1192                                 clause->try_len = ex_info->len;
1193                         clause->handler_offset = ex_block->start;
1194                         clause->handler_len = ex_block->len;
1195                         if (ex_block->extype) {
1196                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1197
1198                                 if (!is_ok (error)) {
1199                                         image_g_free (image, clauses);
1200                                         return NULL;
1201                                 }
1202                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1203                         } else {
1204                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1205                                         clause->data.filter_offset = ex_block->filter_offset;
1206                                 else
1207                                         clause->data.filter_offset = 0;
1208                         }
1209                         finally_start = ex_block->start + ex_block->len;
1210
1211                         clause_index ++;
1212                 }
1213         }
1214
1215         return clauses;
1216 }
1217 #endif /* !DISABLE_REFLECTION_EMIT */
1218
1219 /**
1220  * method_encode_code:
1221  *
1222  * @assembly the assembly
1223  * @mb the managed MethodBuilder
1224  * @error set on error
1225  *
1226  * Note that the return value is not sensible if @error is set.
1227  */
1228 static guint32
1229 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1230 {
1231         MONO_REQ_GC_UNSAFE_MODE;
1232
1233         char flags = 0;
1234         guint32 idx;
1235         guint32 code_size;
1236         gint32 max_stack, i;
1237         gint32 num_locals = 0;
1238         gint32 num_exception = 0;
1239         gint maybe_small;
1240         guint32 fat_flags;
1241         char fat_header [12];
1242         guint32 int_value;
1243         guint16 short_value;
1244         guint32 local_sig = 0;
1245         guint32 header_size = 12;
1246         MonoArray *code;
1247
1248         mono_error_init (error);
1249
1250         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1251                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1252                 return 0;
1253
1254         /*if (mb->name)
1255                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1256         if (mb->ilgen) {
1257                 code = mb->ilgen->code;
1258                 code_size = mb->ilgen->code_len;
1259                 max_stack = mb->ilgen->max_stack;
1260                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1261                 if (mb->ilgen->ex_handlers)
1262                         num_exception = method_count_clauses (mb->ilgen);
1263         } else {
1264                 code = mb->code;
1265                 if (code == NULL){
1266                         char *name = mono_string_to_utf8 (mb->name);
1267                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1268                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1269                         g_free (str);
1270                         g_free (name);
1271                         return 0;
1272                 }
1273
1274                 code_size = mono_array_length (code);
1275                 max_stack = 8; /* we probably need to run a verifier on the code... */
1276         }
1277
1278         stream_data_align (&assembly->code);
1279
1280         /* check for exceptions, maxstack, locals */
1281         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1282         if (maybe_small) {
1283                 if (code_size < 64 && !(code_size & 1)) {
1284                         flags = (code_size << 2) | 0x2;
1285                 } else if (code_size < 32 && (code_size & 1)) {
1286                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1287                 } else {
1288                         goto fat_header;
1289                 }
1290                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1291                 /* add to the fixup todo list */
1292                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1293                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1294                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1295                 return assembly->text_rva + idx;
1296         } 
1297 fat_header:
1298         if (num_locals) {
1299                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1300                 return_val_if_nok (error, 0);
1301         }
1302         /* 
1303          * FIXME: need to set also the header size in fat_flags.
1304          * (and more sects and init locals flags)
1305          */
1306         fat_flags =  0x03;
1307         if (num_exception)
1308                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1309         if (mb->init_locals)
1310                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1311         fat_header [0] = fat_flags;
1312         fat_header [1] = (header_size / 4 ) << 4;
1313         short_value = GUINT16_TO_LE (max_stack);
1314         memcpy (fat_header + 2, &short_value, 2);
1315         int_value = GUINT32_TO_LE (code_size);
1316         memcpy (fat_header + 4, &int_value, 4);
1317         int_value = GUINT32_TO_LE (local_sig);
1318         memcpy (fat_header + 8, &int_value, 4);
1319         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1320         /* add to the fixup todo list */
1321         if (mb->ilgen && mb->ilgen->num_token_fixups)
1322                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1323         
1324         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1325         if (num_exception) {
1326                 unsigned char sheader [4];
1327                 MonoILExceptionInfo * ex_info;
1328                 MonoILExceptionBlock * ex_block;
1329                 int j;
1330
1331                 stream_data_align (&assembly->code);
1332                 /* always use fat format for now */
1333                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1334                 num_exception *= 6 * sizeof (guint32);
1335                 num_exception += 4; /* include the size of the header */
1336                 sheader [1] = num_exception & 0xff;
1337                 sheader [2] = (num_exception >> 8) & 0xff;
1338                 sheader [3] = (num_exception >> 16) & 0xff;
1339                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1340                 /* fat header, so we are already aligned */
1341                 /* reverse order */
1342                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1343                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1344                         if (ex_info->handlers) {
1345                                 int finally_start = ex_info->start + ex_info->len;
1346                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1347                                         guint32 val;
1348                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1349                                         /* the flags */
1350                                         val = GUINT32_TO_LE (ex_block->type);
1351                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1352                                         /* try offset */
1353                                         val = GUINT32_TO_LE (ex_info->start);
1354                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1355                                         /* need fault, too, probably */
1356                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1357                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1358                                         else
1359                                                 val = GUINT32_TO_LE (ex_info->len);
1360                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1361                                         /* handler offset */
1362                                         val = GUINT32_TO_LE (ex_block->start);
1363                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1364                                         /* handler len */
1365                                         val = GUINT32_TO_LE (ex_block->len);
1366                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1367                                         finally_start = ex_block->start + ex_block->len;
1368                                         if (ex_block->extype) {
1369                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1370                                                 return_val_if_nok (error, 0);
1371
1372                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1373                                         } else {
1374                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1375                                                         val = ex_block->filter_offset;
1376                                                 else
1377                                                         val = 0;
1378                                         }
1379                                         val = GUINT32_TO_LE (val);
1380                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1381                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1382                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1383                                 }
1384                         } else {
1385                                 g_error ("No clauses for ex info block %d", i);
1386                         }
1387                 }
1388         }
1389         return assembly->text_rva + idx;
1390 }
1391
1392 static guint32
1393 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1394 {
1395         MONO_REQ_GC_NEUTRAL_MODE;
1396
1397         int i;
1398         MonoDynamicTable *table;
1399         guint32 *values;
1400         
1401         table = &assembly->tables [table_idx];
1402
1403         g_assert (col < table->columns);
1404
1405         values = table->values + table->columns;
1406         for (i = 1; i <= table->rows; ++i) {
1407                 if (values [col] == token)
1408                         return i;
1409                 values += table->columns;
1410         }
1411         return 0;
1412 }
1413
1414 /*
1415  * LOCKING: Acquires the loader lock. 
1416  */
1417 static MonoCustomAttrInfo*
1418 lookup_custom_attr (MonoImage *image, gpointer member)
1419 {
1420         MONO_REQ_GC_NEUTRAL_MODE;
1421
1422         MonoCustomAttrInfo* res;
1423
1424         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1425
1426         if (!res)
1427                 return NULL;
1428
1429         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1430         res->cached = 0;
1431         return res;
1432 }
1433
1434 static gboolean
1435 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1436 {
1437         MONO_REQ_GC_UNSAFE_MODE;
1438
1439         /* FIXME: Need to do more checks */
1440         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1441                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1442
1443                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1444                         return FALSE;
1445         }
1446
1447         return TRUE;
1448 }
1449
1450 static MonoCustomAttrInfo*
1451 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1452 {
1453         MONO_REQ_GC_UNSAFE_MODE;
1454
1455         int i, index, count, not_visible;
1456         MonoCustomAttrInfo *ainfo;
1457         MonoReflectionCustomAttr *cattr;
1458
1459         if (!cattrs)
1460                 return NULL;
1461         /* FIXME: check in assembly the Run flag is set */
1462
1463         count = mono_array_length (cattrs);
1464
1465         /* Skip nonpublic attributes since MS.NET seems to do the same */
1466         /* FIXME: This needs to be done more globally */
1467         not_visible = 0;
1468         for (i = 0; i < count; ++i) {
1469                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1470                 if (!custom_attr_visible (image, cattr))
1471                         not_visible ++;
1472         }
1473         count -= not_visible;
1474
1475         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1476
1477         ainfo->image = image;
1478         ainfo->num_attrs = count;
1479         ainfo->cached = alloc_img != NULL;
1480         index = 0;
1481         for (i = 0; i < count; ++i) {
1482                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1483                 if (custom_attr_visible (image, cattr)) {
1484                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1485                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1486                         ainfo->attrs [index].ctor = cattr->ctor->method;
1487                         ainfo->attrs [index].data = saved;
1488                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1489                         index ++;
1490                 }
1491         }
1492
1493         return ainfo;
1494 }
1495
1496 #ifndef DISABLE_REFLECTION_EMIT
1497 /*
1498  * LOCKING: Acquires the loader lock. 
1499  */
1500 static void
1501 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1502 {
1503         MONO_REQ_GC_UNSAFE_MODE;
1504
1505         MonoCustomAttrInfo *ainfo, *tmp;
1506
1507         if (!cattrs || !mono_array_length (cattrs))
1508                 return;
1509
1510         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1511
1512         mono_loader_lock ();
1513         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1514         if (tmp)
1515                 mono_custom_attrs_free (tmp);
1516         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1517         mono_loader_unlock ();
1518
1519 }
1520 #endif
1521
1522 void
1523 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1524 {
1525         MONO_REQ_GC_NEUTRAL_MODE;
1526
1527         if (ainfo && !ainfo->cached)
1528                 g_free (ainfo);
1529 }
1530
1531 /*
1532  * idx is the table index of the object
1533  * type is one of MONO_CUSTOM_ATTR_*
1534  */
1535 static gboolean
1536 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1537 {
1538         MONO_REQ_GC_UNSAFE_MODE;
1539
1540         MonoDynamicTable *table;
1541         MonoReflectionCustomAttr *cattr;
1542         guint32 *values;
1543         guint32 count, i, token;
1544         char blob_size [6];
1545         char *p = blob_size;
1546         
1547         mono_error_init (error);
1548
1549         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1550         if (!cattrs)
1551                 return TRUE;
1552         count = mono_array_length (cattrs);
1553         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1554         table->rows += count;
1555         alloc_table (table, table->rows);
1556         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1557         idx <<= MONO_CUSTOM_ATTR_BITS;
1558         idx |= type;
1559         for (i = 0; i < count; ++i) {
1560                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1561                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1562                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1563                 if (!mono_error_ok (error)) goto fail;
1564                 type = mono_metadata_token_index (token);
1565                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1566                 switch (mono_metadata_token_table (token)) {
1567                 case MONO_TABLE_METHOD:
1568                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1569                         /*
1570                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1571                          * method, not the one returned by mono_image_create_token ().
1572                          */
1573                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1574                         break;
1575                 case MONO_TABLE_MEMBERREF:
1576                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1577                         break;
1578                 default:
1579                         g_warning ("got wrong token in custom attr");
1580                         continue;
1581                 }
1582                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1583                 p = blob_size;
1584                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1585                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1586                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1587                 values += MONO_CUSTOM_ATTR_SIZE;
1588                 ++table->next_idx;
1589         }
1590
1591         return TRUE;
1592
1593 fail:
1594         return FALSE;
1595 }
1596
1597 static void
1598 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1599 {
1600         MONO_REQ_GC_UNSAFE_MODE;
1601
1602         MonoDynamicTable *table;
1603         guint32 *values;
1604         guint32 count, i, idx;
1605         MonoReflectionPermissionSet *perm;
1606
1607         if (!permissions)
1608                 return;
1609
1610         count = mono_array_length (permissions);
1611         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1612         table->rows += count;
1613         alloc_table (table, table->rows);
1614
1615         for (i = 0; i < mono_array_length (permissions); ++i) {
1616                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1617
1618                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1619
1620                 idx = mono_metadata_token_index (parent_token);
1621                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1622                 switch (mono_metadata_token_table (parent_token)) {
1623                 case MONO_TABLE_TYPEDEF:
1624                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1625                         break;
1626                 case MONO_TABLE_METHOD:
1627                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1628                         break;
1629                 case MONO_TABLE_ASSEMBLY:
1630                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1631                         break;
1632                 default:
1633                         g_assert_not_reached ();
1634                 }
1635
1636                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1637                 values [MONO_DECL_SECURITY_PARENT] = idx;
1638                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1639
1640                 ++table->next_idx;
1641         }
1642 }
1643
1644 /*
1645  * Fill in the MethodDef and ParamDef tables for a method.
1646  * This is used for both normal methods and constructors.
1647  */
1648 static gboolean
1649 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1650 {
1651         MONO_REQ_GC_UNSAFE_MODE;
1652
1653         MonoDynamicTable *table;
1654         guint32 *values;
1655         guint i, count;
1656
1657         mono_error_init (error);
1658
1659         /* room in this table is already allocated */
1660         table = &assembly->tables [MONO_TABLE_METHOD];
1661         *mb->table_idx = table->next_idx ++;
1662         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1663         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1664         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1665         values [MONO_METHOD_FLAGS] = mb->attrs;
1666         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1667         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1670         return_val_if_nok (error, FALSE);
1671
1672         table = &assembly->tables [MONO_TABLE_PARAM];
1673         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1674
1675         mono_image_add_decl_security (assembly, 
1676                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1677
1678         if (mb->pinfo) {
1679                 MonoDynamicTable *mtable;
1680                 guint32 *mvalues;
1681                 
1682                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1683                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1684                 
1685                 count = 0;
1686                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1687                         if (mono_array_get (mb->pinfo, gpointer, i))
1688                                 count++;
1689                 }
1690                 table->rows += count;
1691                 alloc_table (table, table->rows);
1692                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1693                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1694                         MonoReflectionParamBuilder *pb;
1695                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1696                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1697                                 values [MONO_PARAM_SEQUENCE] = i;
1698                                 if (pb->name != NULL) {
1699                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1700                                 } else {
1701                                         values [MONO_PARAM_NAME] = 0;
1702                                 }
1703                                 values += MONO_PARAM_SIZE;
1704                                 if (pb->marshal_info) {
1705                                         mtable->rows++;
1706                                         alloc_table (mtable, mtable->rows);
1707                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1708                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1709                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1710                                         return_val_if_nok (error, FALSE);
1711                                 }
1712                                 pb->table_idx = table->next_idx++;
1713                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1714                                         guint32 field_type = 0;
1715                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1716                                         mtable->rows ++;
1717                                         alloc_table (mtable, mtable->rows);
1718                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1719                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1720                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1721                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1722                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1723                                 }
1724                         }
1725                 }
1726         }
1727
1728         return TRUE;
1729 }
1730
1731 #ifndef DISABLE_REFLECTION_EMIT
1732 static gboolean
1733 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1734 {
1735         MONO_REQ_GC_UNSAFE_MODE;
1736
1737         mono_error_init (error);
1738         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1739
1740         rmb->ilgen = mb->ilgen;
1741         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1742         return_val_if_nok (error, FALSE);
1743         rmb->parameters = mb->parameters;
1744         rmb->generic_params = mb->generic_params;
1745         rmb->generic_container = mb->generic_container;
1746         rmb->opt_types = NULL;
1747         rmb->pinfo = mb->pinfo;
1748         rmb->attrs = mb->attrs;
1749         rmb->iattrs = mb->iattrs;
1750         rmb->call_conv = mb->call_conv;
1751         rmb->code = mb->code;
1752         rmb->type = mb->type;
1753         rmb->name = mb->name;
1754         rmb->table_idx = &mb->table_idx;
1755         rmb->init_locals = mb->init_locals;
1756         rmb->skip_visibility = FALSE;
1757         rmb->return_modreq = mb->return_modreq;
1758         rmb->return_modopt = mb->return_modopt;
1759         rmb->param_modreq = mb->param_modreq;
1760         rmb->param_modopt = mb->param_modopt;
1761         rmb->permissions = mb->permissions;
1762         rmb->mhandle = mb->mhandle;
1763         rmb->nrefs = 0;
1764         rmb->refs = NULL;
1765
1766         if (mb->dll) {
1767                 rmb->charset = mb->charset;
1768                 rmb->extra_flags = mb->extra_flags;
1769                 rmb->native_cc = mb->native_cc;
1770                 rmb->dllentry = mb->dllentry;
1771                 rmb->dll = mb->dll;
1772         }
1773
1774         return TRUE;
1775 }
1776
1777 static gboolean
1778 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1779 {
1780         MONO_REQ_GC_UNSAFE_MODE;
1781
1782         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1783
1784         mono_error_init (error);
1785
1786         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1787
1788         rmb->ilgen = mb->ilgen;
1789         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1790         return_val_if_nok (error, FALSE);
1791         rmb->parameters = mb->parameters;
1792         rmb->generic_params = NULL;
1793         rmb->generic_container = NULL;
1794         rmb->opt_types = NULL;
1795         rmb->pinfo = mb->pinfo;
1796         rmb->attrs = mb->attrs;
1797         rmb->iattrs = mb->iattrs;
1798         rmb->call_conv = mb->call_conv;
1799         rmb->code = NULL;
1800         rmb->type = mb->type;
1801         rmb->name = mono_string_new (mono_domain_get (), name);
1802         rmb->table_idx = &mb->table_idx;
1803         rmb->init_locals = mb->init_locals;
1804         rmb->skip_visibility = FALSE;
1805         rmb->return_modreq = NULL;
1806         rmb->return_modopt = NULL;
1807         rmb->param_modreq = mb->param_modreq;
1808         rmb->param_modopt = mb->param_modopt;
1809         rmb->permissions = mb->permissions;
1810         rmb->mhandle = mb->mhandle;
1811         rmb->nrefs = 0;
1812         rmb->refs = NULL;
1813
1814         return TRUE;
1815 }
1816
1817 static void
1818 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1819 {
1820         MONO_REQ_GC_UNSAFE_MODE;
1821
1822         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1823
1824         rmb->ilgen = mb->ilgen;
1825         rmb->rtype = mb->rtype;
1826         rmb->parameters = mb->parameters;
1827         rmb->generic_params = NULL;
1828         rmb->generic_container = NULL;
1829         rmb->opt_types = NULL;
1830         rmb->pinfo = NULL;
1831         rmb->attrs = mb->attrs;
1832         rmb->iattrs = 0;
1833         rmb->call_conv = mb->call_conv;
1834         rmb->code = NULL;
1835         rmb->type = (MonoObject *) mb->owner;
1836         rmb->name = mb->name;
1837         rmb->table_idx = NULL;
1838         rmb->init_locals = mb->init_locals;
1839         rmb->skip_visibility = mb->skip_visibility;
1840         rmb->return_modreq = NULL;
1841         rmb->return_modopt = NULL;
1842         rmb->param_modreq = NULL;
1843         rmb->param_modopt = NULL;
1844         rmb->permissions = NULL;
1845         rmb->mhandle = mb->mhandle;
1846         rmb->nrefs = 0;
1847         rmb->refs = NULL;
1848 }       
1849 #endif
1850
1851 static gboolean
1852 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1853 {
1854         MONO_REQ_GC_UNSAFE_MODE;
1855
1856         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1857         MonoDynamicTable *table;
1858         guint32 *values;
1859         guint32 tok;
1860         MonoReflectionMethod *m;
1861         int i;
1862
1863         mono_error_init (error);
1864
1865         if (!mb->override_methods)
1866                 return TRUE;
1867
1868         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1869                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1870
1871                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1872                 table->rows ++;
1873                 alloc_table (table, table->rows);
1874                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1875                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1876                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1877
1878                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1879                 return_val_if_nok (error, FALSE);
1880
1881                 switch (mono_metadata_token_table (tok)) {
1882                 case MONO_TABLE_MEMBERREF:
1883                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1884                         break;
1885                 case MONO_TABLE_METHOD:
1886                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1887                         break;
1888                 default:
1889                         g_assert_not_reached ();
1890                 }
1891                 values [MONO_METHODIMPL_DECLARATION] = tok;
1892         }
1893
1894         return TRUE;
1895 }
1896
1897 #ifndef DISABLE_REFLECTION_EMIT
1898 static gboolean
1899 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1900 {
1901         MONO_REQ_GC_UNSAFE_MODE;
1902
1903         MonoDynamicTable *table;
1904         guint32 *values;
1905         ReflectionMethodBuilder rmb;
1906         int i;
1907
1908         mono_error_init (error);
1909
1910         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1911             !mono_image_basic_method (&rmb, assembly, error))
1912                 return FALSE;
1913
1914         mb->table_idx = *rmb.table_idx;
1915
1916         if (mb->dll) { /* It's a P/Invoke method */
1917                 guint32 moduleref;
1918                 /* map CharSet values to on-disk values */
1919                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1920                 int extra_flags = mb->extra_flags;
1921                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1922                 table->rows ++;
1923                 alloc_table (table, table->rows);
1924                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1925                 
1926                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1927                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1928                 if (mb->dllentry)
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1930                 else
1931                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1932                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1933                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1934                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1935                         table->rows ++;
1936                         alloc_table (table, table->rows);
1937                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1938                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1939                 }
1940         }
1941
1942         if (mb->generic_params) {
1943                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1944                 table->rows += mono_array_length (mb->generic_params);
1945                 alloc_table (table, table->rows);
1946                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1947                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1948
1949                         mono_image_get_generic_param_info (
1950                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1951                 }
1952         }
1953
1954         return TRUE;
1955 }
1956
1957 static gboolean
1958 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1959 {
1960         MONO_REQ_GC_UNSAFE_MODE;
1961
1962         ReflectionMethodBuilder rmb;
1963
1964         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1965                 return FALSE;
1966
1967         if (!mono_image_basic_method (&rmb, assembly, error))
1968                 return FALSE;
1969
1970         mb->table_idx = *rmb.table_idx;
1971
1972         return TRUE;
1973 }
1974 #endif
1975
1976 static char*
1977 type_get_fully_qualified_name (MonoType *type)
1978 {
1979         MONO_REQ_GC_NEUTRAL_MODE;
1980
1981         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1982 }
1983
1984 static char*
1985 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1986 {
1987         MONO_REQ_GC_UNSAFE_MODE;
1988
1989         MonoClass *klass;
1990         MonoAssembly *ta;
1991
1992         klass = mono_class_from_mono_type (type);
1993         if (!klass) 
1994                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1995         ta = klass->image->assembly;
1996         if (assembly_is_dynamic (ta) || (ta == ass)) {
1997                 if (klass->generic_class || klass->generic_container)
1998                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
2000                 else
2001                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2002         }
2003
2004         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2005 }
2006
2007 #ifndef DISABLE_REFLECTION_EMIT
2008 /*field_image is the image to which the eventual custom mods have been encoded against*/
2009 static guint32
2010 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2011 {
2012         MONO_REQ_GC_NEUTRAL_MODE;
2013
2014         SigBuffer buf;
2015         guint32 idx, i, token;
2016
2017         if (!assembly->save)
2018                 return 0;
2019
2020         sigbuffer_init (&buf, 32);
2021         
2022         sigbuffer_add_value (&buf, 0x06);
2023         /* encode custom attributes before the type */
2024         if (type->num_mods) {
2025                 for (i = 0; i < type->num_mods; ++i) {
2026                         if (field_image) {
2027                                 MonoError error;
2028                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2029                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2030
2031                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2032                         } else {
2033                                 token = type->modifiers [i].token;
2034                         }
2035
2036                         if (type->modifiers [i].required)
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2038                         else
2039                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2040
2041                         sigbuffer_add_value (&buf, token);
2042                 }
2043         }
2044         encode_type (assembly, type, &buf);
2045         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2046         sigbuffer_free (&buf);
2047         return idx;
2048 }
2049 #endif
2050
2051 static guint32
2052 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2053 {
2054         MONO_REQ_GC_UNSAFE_MODE;
2055
2056         mono_error_init (error);
2057
2058         SigBuffer buf;
2059         guint32 idx;
2060         guint32 typespec = 0;
2061         MonoType *type;
2062         MonoClass *klass;
2063
2064         init_type_builder_generics (fb->type);
2065
2066         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2067         return_val_if_nok (error, 0);
2068         klass = mono_class_from_mono_type (type);
2069
2070         sigbuffer_init (&buf, 32);
2071         
2072         sigbuffer_add_value (&buf, 0x06);
2073         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2074         if (!is_ok (error))
2075                 goto fail;
2076         /* encode custom attributes before the type */
2077
2078         if (klass->generic_container)
2079                 typespec = create_typespec (assembly, type);
2080
2081         if (typespec) {
2082                 MonoGenericClass *gclass;
2083                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2084                 encode_generic_class (assembly, gclass, &buf);
2085         } else {
2086                 encode_type (assembly, type, &buf);
2087         }
2088         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2089         sigbuffer_free (&buf);
2090         return idx;
2091 fail:
2092         sigbuffer_free (&buf);
2093         return 0;
2094 }
2095
2096 static guint32
2097 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2098 {
2099         MONO_REQ_GC_UNSAFE_MODE;
2100
2101         char blob_size [64];
2102         char *b = blob_size;
2103         char *box_val;
2104         char* buf;
2105         guint32 idx = 0, len = 0, dummy = 0;
2106
2107         buf = (char *)g_malloc (64);
2108         if (!val) {
2109                 *ret_type = MONO_TYPE_CLASS;
2110                 len = 4;
2111                 box_val = (char*)&dummy;
2112         } else {
2113                 box_val = ((char*)val) + sizeof (MonoObject);
2114                 *ret_type = val->vtable->klass->byval_arg.type;
2115         }
2116 handle_enum:
2117         switch (*ret_type) {
2118         case MONO_TYPE_BOOLEAN:
2119         case MONO_TYPE_U1:
2120         case MONO_TYPE_I1:
2121                 len = 1;
2122                 break;
2123         case MONO_TYPE_CHAR:
2124         case MONO_TYPE_U2:
2125         case MONO_TYPE_I2:
2126                 len = 2;
2127                 break;
2128         case MONO_TYPE_U4:
2129         case MONO_TYPE_I4:
2130         case MONO_TYPE_R4:
2131                 len = 4;
2132                 break;
2133         case MONO_TYPE_U8:
2134         case MONO_TYPE_I8:
2135                 len = 8;
2136                 break;
2137         case MONO_TYPE_R8:
2138                 len = 8;
2139                 break;
2140         case MONO_TYPE_VALUETYPE: {
2141                 MonoClass *klass = val->vtable->klass;
2142                 
2143                 if (klass->enumtype) {
2144                         *ret_type = mono_class_enum_basetype (klass)->type;
2145                         goto handle_enum;
2146                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2147                         len = 8;
2148                 } else 
2149                         g_error ("we can't encode valuetypes, we should have never reached this line");
2150                 break;
2151         }
2152         case MONO_TYPE_CLASS:
2153                 break;
2154         case MONO_TYPE_STRING: {
2155                 MonoString *str = (MonoString*)val;
2156                 /* there is no signature */
2157                 len = str->length * 2;
2158                 mono_metadata_encode_value (len, b, &b);
2159 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2160                 {
2161                         char *swapped = g_malloc (2 * mono_string_length (str));
2162                         const char *p = (const char*)mono_string_chars (str);
2163
2164                         swap_with_size (swapped, p, 2, mono_string_length (str));
2165                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2166                         g_free (swapped);
2167                 }
2168 #else
2169                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2170 #endif
2171
2172                 g_free (buf);
2173                 return idx;
2174         }
2175         case MONO_TYPE_GENERICINST:
2176                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2177                 goto handle_enum;
2178         default:
2179                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2180         }
2181
2182         /* there is no signature */
2183         mono_metadata_encode_value (len, b, &b);
2184 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2185         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2186         swap_with_size (blob_size, box_val, len, 1);
2187         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2188 #else
2189         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2190 #endif
2191
2192         g_free (buf);
2193         return idx;
2194 }
2195
2196 static guint32
2197 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2198 {
2199         MONO_REQ_GC_UNSAFE_MODE;
2200
2201         mono_error_init (error);
2202
2203         char *str;
2204         SigBuffer buf;
2205         guint32 idx, len;
2206
2207         sigbuffer_init (&buf, 32);
2208
2209         sigbuffer_add_value (&buf, minfo->type);
2210
2211         switch (minfo->type) {
2212         case MONO_NATIVE_BYVALTSTR:
2213         case MONO_NATIVE_BYVALARRAY:
2214                 sigbuffer_add_value (&buf, minfo->count);
2215                 break;
2216         case MONO_NATIVE_LPARRAY:
2217                 if (minfo->eltype || minfo->has_size) {
2218                         sigbuffer_add_value (&buf, minfo->eltype);
2219                         if (minfo->has_size) {
2220                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2221                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2222
2223                                 /* LAMESPEC: ElemMult is undocumented */
2224                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2225                         }
2226                 }
2227                 break;
2228         case MONO_NATIVE_SAFEARRAY:
2229                 if (minfo->eltype)
2230                         sigbuffer_add_value (&buf, minfo->eltype);
2231                 break;
2232         case MONO_NATIVE_CUSTOM:
2233                 if (minfo->guid) {
2234                         str = mono_string_to_utf8 (minfo->guid);
2235                         len = strlen (str);
2236                         sigbuffer_add_value (&buf, len);
2237                         sigbuffer_add_mem (&buf, str, len);
2238                         g_free (str);
2239                 } else {
2240                         sigbuffer_add_value (&buf, 0);
2241                 }
2242                 /* native type name */
2243                 sigbuffer_add_value (&buf, 0);
2244                 /* custom marshaler type name */
2245                 if (minfo->marshaltype || minfo->marshaltyperef) {
2246                         if (minfo->marshaltyperef) {
2247                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2248                                 if (!is_ok (error)) {
2249                                         sigbuffer_free (&buf);
2250                                         return 0;
2251                                 }
2252                                 str = type_get_fully_qualified_name (marshaltype);
2253                         } else
2254                                 str = mono_string_to_utf8 (minfo->marshaltype);
2255                         len = strlen (str);
2256                         sigbuffer_add_value (&buf, len);
2257                         sigbuffer_add_mem (&buf, str, len);
2258                         g_free (str);
2259                 } else {
2260                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2261                         sigbuffer_add_value (&buf, 0);
2262                 }
2263                 if (minfo->mcookie) {
2264                         str = mono_string_to_utf8 (minfo->mcookie);
2265                         len = strlen (str);
2266                         sigbuffer_add_value (&buf, len);
2267                         sigbuffer_add_mem (&buf, str, len);
2268                         g_free (str);
2269                 } else {
2270                         sigbuffer_add_value (&buf, 0);
2271                 }
2272                 break;
2273         default:
2274                 break;
2275         }
2276         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2277         sigbuffer_free (&buf);
2278         return idx;
2279 }
2280
2281 static void
2282 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2283 {
2284         MONO_REQ_GC_UNSAFE_MODE;
2285
2286         mono_error_init (error);
2287
2288         MonoDynamicTable *table;
2289         guint32 *values;
2290
2291         /* maybe this fixup should be done in the C# code */
2292         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2293                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2294         table = &assembly->tables [MONO_TABLE_FIELD];
2295         fb->table_idx = table->next_idx ++;
2296         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2297         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2298         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2299         values [MONO_FIELD_FLAGS] = fb->attrs;
2300         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2301         return_if_nok (error);
2302
2303
2304         if (fb->offset != -1) {
2305                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2306                 table->rows ++;
2307                 alloc_table (table, table->rows);
2308                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2309                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2310                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2311         }
2312         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2313                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2314                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2315                 table->rows ++;
2316                 alloc_table (table, table->rows);
2317                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2318                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2319                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2320                 values [MONO_CONSTANT_TYPE] = field_type;
2321                 values [MONO_CONSTANT_PADDING] = 0;
2322         }
2323         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2324                 guint32 rva_idx;
2325                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2326                 table->rows ++;
2327                 alloc_table (table, table->rows);
2328                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2329                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2330                 /*
2331                  * We store it in the code section because it's simpler for now.
2332                  */
2333                 if (fb->rva_data) {
2334                         if (mono_array_length (fb->rva_data) >= 10)
2335                                 stream_data_align (&assembly->code);
2336                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2337                 } else
2338                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2339                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2340         }
2341         if (fb->marshal_info) {
2342                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2343                 table->rows ++;
2344                 alloc_table (table, table->rows);
2345                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2346                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2347                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2348                 return_if_nok (error);
2349         }
2350 }
2351
2352 static guint32
2353 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2354 {
2355         MONO_REQ_GC_UNSAFE_MODE;
2356
2357         mono_error_init (error);
2358
2359         SigBuffer buf;
2360         guint32 nparams = 0;
2361         MonoReflectionMethodBuilder *mb = fb->get_method;
2362         MonoReflectionMethodBuilder *smb = fb->set_method;
2363         guint32 idx, i;
2364
2365         if (mb && mb->parameters)
2366                 nparams = mono_array_length (mb->parameters);
2367         if (!mb && smb && smb->parameters)
2368                 nparams = mono_array_length (smb->parameters) - 1;
2369         sigbuffer_init (&buf, 32);
2370         if (fb->call_conv & 0x20)
2371                 sigbuffer_add_byte (&buf, 0x28);
2372         else
2373                 sigbuffer_add_byte (&buf, 0x08);
2374         sigbuffer_add_value (&buf, nparams);
2375         if (mb) {
2376                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2377                 if (!is_ok (error))
2378                         goto fail;
2379                 for (i = 0; i < nparams; ++i) {
2380                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2381                         encode_reflection_type (assembly, pt, &buf, error);
2382                         if (!is_ok (error))
2383                                 goto fail;
2384                 }
2385         } else if (smb && smb->parameters) {
2386                 /* the property type is the last param */
2387                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2388                 if (!is_ok (error))
2389                         goto fail;
2390
2391                 for (i = 0; i < nparams; ++i) {
2392                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2393                         encode_reflection_type (assembly, pt, &buf, error);
2394                         if (!is_ok (error))
2395                                 goto fail;
2396                 }
2397         } else {
2398                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2399                 if (!is_ok (error))
2400                         goto fail;
2401         }
2402
2403         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2404         sigbuffer_free (&buf);
2405         return idx;
2406 fail:
2407         sigbuffer_free (&buf);
2408         return 0;
2409 }
2410
2411 static void
2412 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2413 {
2414         MONO_REQ_GC_UNSAFE_MODE;
2415
2416         mono_error_init (error);
2417
2418         MonoDynamicTable *table;
2419         guint32 *values;
2420         guint num_methods = 0;
2421         guint32 semaidx;
2422
2423         /* 
2424          * we need to set things in the following tables:
2425          * PROPERTYMAP (info already filled in _get_type_info ())
2426          * PROPERTY    (rows already preallocated in _get_type_info ())
2427          * METHOD      (method info already done with the generic method code)
2428          * METHODSEMANTICS
2429          * CONSTANT
2430          */
2431         table = &assembly->tables [MONO_TABLE_PROPERTY];
2432         pb->table_idx = table->next_idx ++;
2433         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2434         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2435         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2436         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2437         return_if_nok (error);
2438
2439
2440         /* FIXME: we still don't handle 'other' methods */
2441         if (pb->get_method) num_methods ++;
2442         if (pb->set_method) num_methods ++;
2443
2444         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2445         table->rows += num_methods;
2446         alloc_table (table, table->rows);
2447
2448         if (pb->get_method) {
2449                 semaidx = table->next_idx ++;
2450                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2451                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2452                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2453                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2454         }
2455         if (pb->set_method) {
2456                 semaidx = table->next_idx ++;
2457                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2458                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2459                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2460                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2461         }
2462         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2463                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2464                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2465                 table->rows ++;
2466                 alloc_table (table, table->rows);
2467                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2468                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2469                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2470                 values [MONO_CONSTANT_TYPE] = field_type;
2471                 values [MONO_CONSTANT_PADDING] = 0;
2472         }
2473 }
2474
2475 static void
2476 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2477 {
2478         MONO_REQ_GC_UNSAFE_MODE;
2479
2480         MonoDynamicTable *table;
2481         guint32 *values;
2482         guint num_methods = 0;
2483         guint32 semaidx;
2484
2485         /* 
2486          * we need to set things in the following tables:
2487          * EVENTMAP (info already filled in _get_type_info ())
2488          * EVENT    (rows already preallocated in _get_type_info ())
2489          * METHOD      (method info already done with the generic method code)
2490          * METHODSEMANTICS
2491          */
2492         table = &assembly->tables [MONO_TABLE_EVENT];
2493         eb->table_idx = table->next_idx ++;
2494         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2495         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2496         values [MONO_EVENT_FLAGS] = eb->attrs;
2497         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2498         return_if_nok (error);
2499         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2500
2501         /*
2502          * FIXME: we still don't handle 'other' methods 
2503          */
2504         if (eb->add_method) num_methods ++;
2505         if (eb->remove_method) num_methods ++;
2506         if (eb->raise_method) num_methods ++;
2507
2508         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2509         table->rows += num_methods;
2510         alloc_table (table, table->rows);
2511
2512         if (eb->add_method) {
2513                 semaidx = table->next_idx ++;
2514                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2515                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2516                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2517                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2518         }
2519         if (eb->remove_method) {
2520                 semaidx = table->next_idx ++;
2521                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2522                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2523                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2524                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2525         }
2526         if (eb->raise_method) {
2527                 semaidx = table->next_idx ++;
2528                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2529                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2530                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2531                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2532         }
2533 }
2534
2535 static void
2536 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2537 {
2538         MONO_REQ_GC_UNSAFE_MODE;
2539
2540         mono_error_init (error);
2541
2542         MonoDynamicTable *table;
2543         guint32 num_constraints, i;
2544         guint32 *values;
2545         guint32 table_idx;
2546
2547         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2548         num_constraints = gparam->iface_constraints ?
2549                 mono_array_length (gparam->iface_constraints) : 0;
2550         table->rows += num_constraints;
2551         if (gparam->base_type)
2552                 table->rows++;
2553         alloc_table (table, table->rows);
2554
2555         if (gparam->base_type) {
2556                 table_idx = table->next_idx ++;
2557                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2558
2559                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2560                 return_if_nok (error);
2561                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2562                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2563         }
2564
2565         for (i = 0; i < num_constraints; i++) {
2566                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2567                         gparam->iface_constraints, gpointer, i);
2568
2569                 table_idx = table->next_idx ++;
2570                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2571
2572                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2573                 return_if_nok (error);
2574
2575                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2576                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2577         }
2578 }
2579
2580 static void
2581 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2582 {
2583         MONO_REQ_GC_UNSAFE_MODE;
2584
2585         GenericParamTableEntry *entry;
2586
2587         /*
2588          * The GenericParam table must be sorted according to the `owner' field.
2589          * We need to do this sorting prior to writing the GenericParamConstraint
2590          * table, since we have to use the final GenericParam table indices there
2591          * and they must also be sorted.
2592          */
2593
2594         entry = g_new0 (GenericParamTableEntry, 1);
2595         entry->owner = owner;
2596         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2597         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2598         entry->gparam = gparam;
2599         
2600         g_ptr_array_add (assembly->gen_params, entry);
2601 }
2602
2603 static gboolean
2604 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2605 {
2606         MONO_REQ_GC_UNSAFE_MODE;
2607
2608         MonoDynamicTable *table;
2609         MonoGenericParam *param;
2610         guint32 *values;
2611         guint32 table_idx;
2612
2613         mono_error_init (error);
2614
2615         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2616         table_idx = table->next_idx ++;
2617         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2618
2619         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2620         return_val_if_nok (error, FALSE);
2621
2622         param = gparam_type->data.generic_param;
2623
2624         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2625         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2626         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2627         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2628
2629         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2630                 return FALSE;
2631
2632         encode_constraints (entry->gparam, table_idx, assembly, error);
2633         return_val_if_nok (error, FALSE);
2634
2635         return TRUE;
2636 }
2637
2638 static guint32
2639 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2640 {
2641         MONO_REQ_GC_UNSAFE_MODE;
2642
2643         MonoDynamicTable *table;
2644         guint32 token;
2645         guint32 *values;
2646         guint32 cols [MONO_ASSEMBLY_SIZE];
2647         const char *pubkey;
2648         guint32 publen;
2649
2650         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2651                 return token;
2652
2653         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2654                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2655                 token = table->next_idx ++;
2656                 table->rows ++;
2657                 alloc_table (table, table->rows);
2658                 values = table->values + token * MONO_MODULEREF_SIZE;
2659                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2660
2661                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2662                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2663                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2664
2665                 return token;
2666         }
2667         
2668         if (assembly_is_dynamic (image->assembly))
2669                 /* FIXME: */
2670                 memset (cols, 0, sizeof (cols));
2671         else {
2672                 /* image->assembly->image is the manifest module */
2673                 image = image->assembly->image;
2674                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2675         }
2676
2677         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2678         token = table->next_idx ++;
2679         table->rows ++;
2680         alloc_table (table, table->rows);
2681         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2682         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2683         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2684         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2685         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2686         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2687         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2688         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2689         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2690
2691         if (strcmp ("", image->assembly->aname.culture)) {
2692                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2693                                 image->assembly->aname.culture);
2694         }
2695
2696         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2697                 guchar pubtoken [9];
2698                 pubtoken [0] = 8;
2699                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2701         } else {
2702                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2703         }
2704         token <<= MONO_RESOLUTION_SCOPE_BITS;
2705         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2706         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2707         return token;
2708 }
2709
2710 static guint32
2711 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2712 {
2713         MONO_REQ_GC_NEUTRAL_MODE;
2714
2715         MonoDynamicTable *table;
2716         guint32 *values;
2717         guint32 token;
2718         SigBuffer buf;
2719
2720         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2721                 return token;
2722
2723         sigbuffer_init (&buf, 32);
2724         switch (type->type) {
2725         case MONO_TYPE_FNPTR:
2726         case MONO_TYPE_PTR:
2727         case MONO_TYPE_SZARRAY:
2728         case MONO_TYPE_ARRAY:
2729         case MONO_TYPE_VAR:
2730         case MONO_TYPE_MVAR:
2731         case MONO_TYPE_GENERICINST:
2732                 encode_type (assembly, type, &buf);
2733                 break;
2734         case MONO_TYPE_CLASS:
2735         case MONO_TYPE_VALUETYPE: {
2736                 MonoClass *k = mono_class_from_mono_type (type);
2737                 if (!k || !k->generic_container) {
2738                         sigbuffer_free (&buf);
2739                         return 0;
2740                 }
2741                 encode_type (assembly, type, &buf);
2742                 break;
2743         }
2744         default:
2745                 sigbuffer_free (&buf);
2746                 return 0;
2747         }
2748
2749         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2750         if (assembly->save) {
2751                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2752                 alloc_table (table, table->rows + 1);
2753                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2754                 values [MONO_TYPESPEC_SIGNATURE] = token;
2755         }
2756         sigbuffer_free (&buf);
2757
2758         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2759         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2760         table->next_idx ++;
2761         return token;
2762 }
2763
2764 static guint32
2765 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2766 {
2767         MONO_REQ_GC_UNSAFE_MODE;
2768
2769         MonoDynamicTable *table;
2770         guint32 *values;
2771         guint32 token, scope, enclosing;
2772         MonoClass *klass;
2773
2774         /* if the type requires a typespec, we must try that first*/
2775         if (try_typespec && (token = create_typespec (assembly, type)))
2776                 return token;
2777         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2778         if (token)
2779                 return token;
2780         klass = mono_class_from_mono_type (type);
2781         if (!klass)
2782                 klass = mono_class_from_mono_type (type);
2783
2784         /*
2785          * If it's in the same module and not a generic type parameter:
2786          */
2787         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2788                         (type->type != MONO_TYPE_MVAR)) {
2789                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2790                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2791                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2792                 return token;
2793         }
2794
2795         if (klass->nested_in) {
2796                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2797                 /* get the typeref idx of the enclosing type */
2798                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2799                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2800         } else {
2801                 scope = resolution_scope_from_image (assembly, klass->image);
2802         }
2803         table = &assembly->tables [MONO_TABLE_TYPEREF];
2804         if (assembly->save) {
2805                 alloc_table (table, table->rows + 1);
2806                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2807                 values [MONO_TYPEREF_SCOPE] = scope;
2808                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2809                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2810         }
2811         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2812         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2813         table->next_idx ++;
2814         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2815         return token;
2816 }
2817
2818 /*
2819  * Despite the name, we handle also TypeSpec (with the above helper).
2820  */
2821 static guint32
2822 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2823 {
2824         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2825 }
2826
2827 #ifndef DISABLE_REFLECTION_EMIT
2828 static guint32
2829 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2830 {
2831         MONO_REQ_GC_NEUTRAL_MODE;
2832
2833         MonoDynamicTable *table;
2834         guint32 *values;
2835         guint32 token, pclass;
2836
2837         switch (parent & MONO_TYPEDEFORREF_MASK) {
2838         case MONO_TYPEDEFORREF_TYPEREF:
2839                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2840                 break;
2841         case MONO_TYPEDEFORREF_TYPESPEC:
2842                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2843                 break;
2844         case MONO_TYPEDEFORREF_TYPEDEF:
2845                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2846                 break;
2847         default:
2848                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2849                 return 0;
2850         }
2851         /* extract the index */
2852         parent >>= MONO_TYPEDEFORREF_BITS;
2853
2854         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2855
2856         if (assembly->save) {
2857                 alloc_table (table, table->rows + 1);
2858                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2859                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2860                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2861                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2862         }
2863
2864         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2865         table->next_idx ++;
2866
2867         return token;
2868 }
2869
2870 /*
2871  * Insert a memberef row into the metadata: the token that point to the memberref
2872  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2873  * mono_image_get_fieldref_token()).
2874  * The sig param is an index to an already built signature.
2875  */
2876 static guint32
2877 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2878 {
2879         MONO_REQ_GC_NEUTRAL_MODE;
2880
2881         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2882         return mono_image_add_memberef_row (assembly, parent, name, sig);
2883 }
2884
2885
2886 static guint32
2887 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2888 {
2889         MONO_REQ_GC_NEUTRAL_MODE;
2890
2891         guint32 token;
2892         MonoMethodSignature *sig;
2893         
2894         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2895
2896         if (create_typespec) {
2897                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2898                 if (token)
2899                         return token;
2900         } 
2901
2902         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2903         if (token && !create_typespec)
2904                 return token;
2905
2906         g_assert (!method->is_inflated);
2907         if (!token) {
2908                 /*
2909                  * A methodref signature can't contain an unmanaged calling convention.
2910                  */
2911                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2912                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2913                         sig->call_convention = MONO_CALL_DEFAULT;
2914                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2915                         method->name,  method_encode_signature (assembly, sig));
2916                 g_free (sig);
2917                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2918         }
2919
2920         if (create_typespec) {
2921                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2922                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2923                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2924
2925                 if (assembly->save) {
2926                         guint32 *values;
2927
2928                         alloc_table (table, table->rows + 1);
2929                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2930                         values [MONO_METHODSPEC_METHOD] = token;
2931                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2932                 }
2933
2934                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2935                 table->next_idx ++;
2936                 /*methodspec and memberef tokens are diferent, */
2937                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2938                 return token;
2939         }
2940         return token;
2941 }
2942
2943 static guint32
2944 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2945 {
2946         guint32 token, parent, sig;
2947         ReflectionMethodBuilder rmb;
2948         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2949         
2950         mono_error_init (error);
2951         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2952         if (token)
2953                 return token;
2954
2955         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2956                 return 0;
2957
2958         /*
2959          * A methodref signature can't contain an unmanaged calling convention.
2960          * Since some flags are encoded as part of call_conv, we need to check against it.
2961         */
2962         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2963                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2964
2965         sig = method_builder_encode_signature (assembly, &rmb, error);
2966         return_val_if_nok (error, 0);
2967
2968         if (tb->generic_params) {
2969                 parent = create_generic_typespec (assembly, tb, error);
2970                 return_val_if_nok (error, 0);
2971         } else {
2972                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2973                 return_val_if_nok (error, 0);
2974
2975                 parent = mono_image_typedef_or_ref (assembly, t);
2976         }
2977
2978         char *name = mono_string_to_utf8 (method->name);
2979
2980         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2981         g_free (name);
2982
2983         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2984
2985         return token;
2986 }
2987
2988 static guint32
2989 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2990                                      const gchar *name, guint32 sig)
2991 {
2992         MonoDynamicTable *table;
2993         guint32 token;
2994         guint32 *values;
2995         
2996         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2997
2998         if (assembly->save) {
2999                 alloc_table (table, table->rows + 1);
3000                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3001                 values [MONO_MEMBERREF_CLASS] = original;
3002                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3003                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3004         }
3005
3006         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3007         table->next_idx ++;
3008
3009         return token;
3010 }
3011
3012 static guint32
3013 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3014 {
3015         SigBuffer buf;
3016         int i;
3017         guint32 nparams = mono_array_length (mb->generic_params);
3018         guint32 idx;
3019
3020         if (!assembly->save)
3021                 return 0;
3022
3023         sigbuffer_init (&buf, 32);
3024
3025         sigbuffer_add_value (&buf, 0xa);
3026         sigbuffer_add_value (&buf, nparams);
3027
3028         for (i = 0; i < nparams; i++) {
3029                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3030                 sigbuffer_add_value (&buf, i);
3031         }
3032
3033         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3034         sigbuffer_free (&buf);
3035         return idx;
3036 }
3037
3038 static guint32
3039 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3040 {
3041         MonoDynamicTable *table;
3042         guint32 *values;
3043         guint32 token, mtoken = 0;
3044
3045         mono_error_init (error);
3046         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3047         if (token)
3048                 return token;
3049
3050         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3051
3052         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3053         if (!mono_error_ok (error))
3054                 return 0;
3055
3056         switch (mono_metadata_token_table (mtoken)) {
3057         case MONO_TABLE_MEMBERREF:
3058                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3059                 break;
3060         case MONO_TABLE_METHOD:
3061                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3062                 break;
3063         default:
3064                 g_assert_not_reached ();
3065         }
3066
3067         if (assembly->save) {
3068                 alloc_table (table, table->rows + 1);
3069                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3070                 values [MONO_METHODSPEC_METHOD] = mtoken;
3071                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3072         }
3073
3074         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3075         table->next_idx ++;
3076
3077         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3078         return token;
3079 }
3080
3081 static guint32
3082 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3083 {
3084         guint32 token;
3085
3086         mono_error_init (error);
3087
3088         if (mb->generic_params && create_methodspec) 
3089                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3090
3091         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3092         if (token)
3093                 return token;
3094
3095         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3096         if (!mono_error_ok (error))
3097                 return 0;
3098         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3099         return token;
3100 }
3101
3102 static guint32
3103 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3104 {
3105         guint32 token, parent, sig;
3106         ReflectionMethodBuilder rmb;
3107         char *name;
3108         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3109         
3110         mono_error_init (error);
3111         
3112         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3113         if (token)
3114                 return token;
3115
3116         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3117                 return 0;
3118
3119         if (tb->generic_params) {
3120                 parent = create_generic_typespec (assembly, tb, error);
3121                 return_val_if_nok (error, 0);
3122         } else {
3123                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3124                 return_val_if_nok (error, 0);
3125                 parent = mono_image_typedef_or_ref (assembly, type);
3126         }
3127         
3128         name = mono_string_to_utf8 (rmb.name);
3129         sig = method_builder_encode_signature (assembly, &rmb, error);
3130         return_val_if_nok (error, 0);
3131
3132         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3133
3134         g_free (name);
3135         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3136         return token;
3137 }
3138 #endif
3139
3140 static gboolean
3141 is_field_on_inst (MonoClassField *field)
3142 {
3143         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3144 }
3145
3146 /*
3147  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3148  */
3149 static MonoType*
3150 get_field_on_inst_generic_type (MonoClassField *field)
3151 {
3152         MonoClass *klass, *gtd;
3153         MonoDynamicGenericClass *dgclass;
3154         int field_index;
3155
3156         g_assert (is_field_on_inst (field));
3157
3158         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3159
3160         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3161                 field_index = field - dgclass->fields;
3162                 return dgclass->field_generic_types [field_index];              
3163         }
3164
3165         klass = field->parent;
3166         gtd = klass->generic_class->container_class;
3167
3168         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3169                 field_index = field - klass->fields;
3170                 return gtd->fields [field_index].type;
3171         }
3172
3173         g_assert_not_reached ();
3174         return 0;
3175 }
3176
3177 #ifndef DISABLE_REFLECTION_EMIT
3178 static guint32
3179 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3180 {
3181         MonoType *type;
3182         guint32 token;
3183
3184         g_assert (field);
3185         g_assert (field->parent);
3186
3187         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3188         if (token)
3189                 return token;
3190
3191         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3192                 int index = field - field->parent->fields;
3193                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3194         } else {
3195                 if (is_field_on_inst (field))
3196                         type = get_field_on_inst_generic_type (field);
3197                 else
3198                         type = mono_field_get_type (field);
3199         }
3200         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3201                                                                                         mono_field_get_name (field),
3202                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3203         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3204         return token;
3205 }
3206
3207 static guint32
3208 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3209 {
3210         guint32 token;
3211         MonoClass *klass;
3212         MonoGenericClass *gclass;
3213         MonoType *type;
3214         char *name;
3215
3216         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3217         if (token)
3218                 return token;
3219         if (is_sre_field_builder (mono_object_class (f->fb))) {
3220                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3221                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3222                 return_val_if_nok (error, 0);
3223                 klass = mono_class_from_mono_type (type);
3224                 gclass = type->data.generic_class;
3225                 g_assert (gclass->is_dynamic);
3226
3227                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3228                 return_val_if_nok (error, 0);
3229                 name = mono_string_to_utf8 (fb->name);
3230                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3231                 g_free (name);          
3232         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3233                 guint32 sig;
3234                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3235
3236                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3237                 return_val_if_nok (error, 0);
3238                 klass = mono_class_from_mono_type (type);
3239
3240                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3241                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3242         } else {
3243                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3244                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3245         }
3246
3247         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3248         return token;
3249 }
3250
3251 static guint32
3252 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3253 {
3254         guint32 sig, token;
3255         MonoClass *klass;
3256         MonoGenericClass *gclass;
3257         MonoType *type;
3258
3259         mono_error_init (error);
3260
3261         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3262
3263         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3264         if (token)
3265                 return token;
3266
3267         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3268                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3269                 ReflectionMethodBuilder rmb;
3270                 char *name;
3271
3272                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3273                 return_val_if_nok (error, 0);
3274                 klass = mono_class_from_mono_type (type);
3275
3276                 gclass = type->data.generic_class;
3277                 g_assert (gclass->is_dynamic);
3278
3279                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3280                         return 0;
3281
3282                 sig = method_builder_encode_signature (assembly, &rmb, error);
3283                 return_val_if_nok (error, 0);
3284
3285                 name = mono_string_to_utf8 (rmb.name);
3286
3287                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3288                 g_free (name);
3289         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3290                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3291
3292                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3293                 return_val_if_nok (error, 0);
3294                 klass = mono_class_from_mono_type (type);
3295
3296                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3297                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3298         } else {
3299                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3300                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3301         }
3302
3303
3304         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3305         return token;
3306 }
3307
3308 static MonoMethod*
3309 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3310 {
3311         MonoClass *klass;
3312         MonoGenericContext tmp_context;
3313         MonoType **type_argv;
3314         MonoGenericInst *ginst;
3315         MonoMethod *method, *inflated;
3316         int count, i;
3317
3318         mono_error_init (error);
3319
3320         init_type_builder_generics ((MonoObject*)m->inst);
3321
3322         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3323         return_val_if_nok (error, NULL);
3324
3325         klass = method->klass;
3326
3327         if (m->method_args == NULL)
3328                 return method;
3329
3330         if (method->is_inflated)
3331                 method = ((MonoMethodInflated *) method)->declaring;
3332
3333         count = mono_array_length (m->method_args);
3334
3335         type_argv = g_new0 (MonoType *, count);
3336         for (i = 0; i < count; i++) {
3337                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3338                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3339                 return_val_if_nok (error, NULL);
3340         }
3341         ginst = mono_metadata_get_generic_inst (count, type_argv);
3342         g_free (type_argv);
3343
3344         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3345         tmp_context.method_inst = ginst;
3346
3347         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3348         mono_error_assert_ok (error);
3349         return inflated;
3350 }
3351
3352 static guint32
3353 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3354 {
3355         guint32 sig, token = 0;
3356         MonoType *type;
3357         MonoClass *klass;
3358
3359         mono_error_init (error);
3360
3361         if (m->method_args) {
3362                 MonoMethod *inflated;
3363
3364                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3365                 return_val_if_nok (error, 0);
3366
3367                 if (create_methodspec)
3368                         token = mono_image_get_methodspec_token (assembly, inflated);
3369                 else
3370                         token = mono_image_get_inflated_method_token (assembly, inflated);
3371                 return token;
3372         }
3373
3374         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3375         if (token)
3376                 return token;
3377
3378         if (is_sre_method_builder (mono_object_class (m->mb))) {
3379                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3380                 MonoGenericClass *gclass;
3381                 ReflectionMethodBuilder rmb;
3382                 char *name;
3383
3384                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3385                 return_val_if_nok (error, 0);
3386                 klass = mono_class_from_mono_type (type);
3387                 gclass = type->data.generic_class;
3388                 g_assert (gclass->is_dynamic);
3389
3390                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3391                         return 0;
3392
3393                 sig = method_builder_encode_signature (assembly, &rmb, error);
3394                 return_val_if_nok (error, 0);
3395
3396                 name = mono_string_to_utf8 (rmb.name);
3397
3398                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3399                 g_free (name);          
3400         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3401                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3402
3403                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3404                 return_val_if_nok (error, 0);
3405                 klass = mono_class_from_mono_type (type);
3406
3407                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3408                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3409         } else {
3410                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3411                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3412         }
3413
3414         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3415         return token;
3416 }
3417
3418 static guint32
3419 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3420 {
3421         SigBuffer buf;
3422         int i;
3423         guint32 nparams = context->method_inst->type_argc;
3424         guint32 idx;
3425
3426         if (!assembly->save)
3427                 return 0;
3428
3429         sigbuffer_init (&buf, 32);
3430         /*
3431          * FIXME: vararg, explicit_this, differenc call_conv values...
3432          */
3433         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3434         sigbuffer_add_value (&buf, nparams);
3435
3436         for (i = 0; i < nparams; i++)
3437                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3438
3439         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3440         sigbuffer_free (&buf);
3441         return idx;
3442 }
3443
3444 static guint32
3445 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3446 {
3447         MonoDynamicTable *table;
3448         guint32 *values;
3449         guint32 token, mtoken = 0, sig;
3450         MonoMethodInflated *imethod;
3451         MonoMethod *declaring;
3452
3453         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3454
3455         g_assert (method->is_inflated);
3456         imethod = (MonoMethodInflated *) method;
3457         declaring = imethod->declaring;
3458
3459         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3460         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3461
3462         if (!mono_method_signature (declaring)->generic_param_count)
3463                 return mtoken;
3464
3465         switch (mono_metadata_token_table (mtoken)) {
3466         case MONO_TABLE_MEMBERREF:
3467                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3468                 break;
3469         case MONO_TABLE_METHOD:
3470                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3471                 break;
3472         default:
3473                 g_assert_not_reached ();
3474         }
3475
3476         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3477
3478         if (assembly->save) {
3479                 alloc_table (table, table->rows + 1);
3480                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3481                 values [MONO_METHODSPEC_METHOD] = mtoken;
3482                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3483         }
3484
3485         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3486         table->next_idx ++;
3487
3488         return token;
3489 }
3490
3491 static guint32
3492 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3493 {
3494         MonoMethodInflated *imethod;
3495         guint32 token;
3496         
3497         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3498         if (token)
3499                 return token;
3500
3501         g_assert (method->is_inflated);
3502         imethod = (MonoMethodInflated *) method;
3503
3504         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3505                 token = method_encode_methodspec (assembly, method);
3506         } else {
3507                 guint32 sig = method_encode_signature (
3508                         assembly, mono_method_signature (imethod->declaring));
3509                 token = mono_image_get_memberref_token (
3510                         assembly, &method->klass->byval_arg, method->name, sig);
3511         }
3512
3513         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3514         return token;
3515 }
3516
3517 static guint32
3518 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3519 {
3520         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3521         guint32 sig, token;
3522
3523         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3524         token = mono_image_get_memberref_token (
3525                 assembly, &m->klass->byval_arg, m->name, sig);
3526
3527         return token;
3528 }
3529
3530 static guint32
3531 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3532 {
3533         MonoDynamicTable *table;
3534         MonoClass *klass;
3535         MonoType *type;
3536         guint32 *values;
3537         guint32 token;
3538         SigBuffer buf;
3539         int count, i;
3540
3541         /*
3542          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3543          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3544          * Because of this, we must not insert it into the `typeref' hash table.
3545          */
3546         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3547         return_val_if_nok (error, 0);
3548         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3549         if (token)
3550                 return token;
3551
3552         sigbuffer_init (&buf, 32);
3553
3554         g_assert (tb->generic_params);
3555         klass = mono_class_from_mono_type (type);
3556
3557         if (tb->generic_container)
3558                 mono_reflection_create_generic_class (tb);
3559
3560         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3561         g_assert (klass->generic_container);
3562         sigbuffer_add_value (&buf, klass->byval_arg.type);
3563         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3564
3565         count = mono_array_length (tb->generic_params);
3566         sigbuffer_add_value (&buf, count);
3567         for (i = 0; i < count; i++) {
3568                 MonoReflectionGenericParam *gparam;
3569
3570                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3571                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3572                 if (!is_ok (error))
3573                         goto fail;
3574
3575                 encode_type (assembly, gparam_type, &buf);
3576         }
3577
3578         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3579
3580         if (assembly->save) {
3581                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3582                 alloc_table (table, table->rows + 1);
3583                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3584                 values [MONO_TYPESPEC_SIGNATURE] = token;
3585         }
3586         sigbuffer_free (&buf);
3587
3588         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3589         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3590         table->next_idx ++;
3591         return token;
3592 fail:
3593         sigbuffer_free (&buf);
3594         return 0;
3595 }
3596
3597 /*
3598  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3599  */
3600 static MonoType*
3601 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3602 {
3603         int i, count, len, pos;
3604         MonoType *t;
3605
3606         mono_error_init (error);
3607
3608         count = 0;
3609         if (modreq)
3610                 count += mono_array_length (modreq);
3611         if (modopt)
3612                 count += mono_array_length (modopt);
3613
3614         if (count == 0)
3615                 return mono_metadata_type_dup (NULL, type);
3616
3617         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3618         t = (MonoType *)g_malloc (len);
3619         memcpy (t, type, MONO_SIZEOF_TYPE);
3620
3621         t->num_mods = count;
3622         pos = 0;
3623         if (modreq) {
3624                 for (i = 0; i < mono_array_length (modreq); ++i) {
3625                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3626                         if (!is_ok (error))
3627                                 goto fail;
3628                         t->modifiers [pos].required = 1;
3629                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3630                         pos ++;
3631                 }
3632         }
3633         if (modopt) {
3634                 for (i = 0; i < mono_array_length (modopt); ++i) {
3635                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3636                         if (!is_ok (error))
3637                                 goto fail;
3638                         t->modifiers [pos].required = 0;
3639                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3640                         pos ++;
3641                 }
3642         }
3643
3644         return t;
3645 fail:
3646         g_free (t);
3647         return NULL;
3648 }
3649
3650 static void
3651 init_type_builder_generics (MonoObject *type)
3652 {
3653         MonoReflectionTypeBuilder *tb;
3654
3655         if (!is_sre_type_builder(mono_object_class (type)))
3656                 return;
3657         tb = (MonoReflectionTypeBuilder *)type;
3658
3659         if (tb && tb->generic_container)
3660                 mono_reflection_create_generic_class (tb);
3661 }
3662
3663 static guint32
3664 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3665 {
3666         MonoDynamicTable *table;
3667         MonoType *custom = NULL, *type;
3668         guint32 *values;
3669         guint32 token, pclass, parent, sig;
3670         gchar *name;
3671
3672         mono_error_init (error);
3673
3674         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3675         if (token)
3676                 return token;
3677
3678         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3679         return_val_if_nok (error, 0);
3680         /* FIXME: is this call necessary? */
3681         mono_class_from_mono_type (typeb);
3682
3683         /*FIXME this is one more layer of ugliness due how types are created.*/
3684         init_type_builder_generics (fb->type);
3685
3686         /* fb->type does not include the custom modifiers */
3687         /* FIXME: We should do this in one place when a fieldbuilder is created */
3688         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3689         return_val_if_nok (error, 0);
3690
3691         if (fb->modreq || fb->modopt) {
3692                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3693                 return_val_if_nok (error, 0);
3694         }
3695
3696         sig = fieldref_encode_signature (assembly, NULL, type);
3697         g_free (custom);
3698
3699         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3700         return_val_if_nok (error, 0);
3701         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3702         
3703         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3704         parent >>= MONO_TYPEDEFORREF_BITS;
3705
3706         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3707
3708         name = mono_string_to_utf8 (fb->name);
3709
3710         if (assembly->save) {
3711                 alloc_table (table, table->rows + 1);
3712                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3713                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3714                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3715                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3716         }
3717
3718         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3719         table->next_idx ++;
3720         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3721         g_free (name);
3722         return token;
3723 }
3724
3725 static guint32
3726 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3727 {
3728         SigBuffer buf;
3729         guint32 nargs;
3730         guint32 i, idx;
3731
3732         mono_error_init (error);
3733
3734         if (!assembly->save)
3735                 return 0;
3736
3737         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3738         g_assert (helper->type == 2);
3739
3740         if (helper->arguments)
3741                 nargs = mono_array_length (helper->arguments);
3742         else
3743                 nargs = 0;
3744
3745         sigbuffer_init (&buf, 32);
3746
3747         /* Encode calling convention */
3748         /* Change Any to Standard */
3749         if ((helper->call_conv & 0x03) == 0x03)
3750                 helper->call_conv = 0x01;
3751         /* explicit_this implies has_this */
3752         if (helper->call_conv & 0x40)
3753                 helper->call_conv &= 0x20;
3754
3755         if (helper->call_conv == 0) { /* Unmanaged */
3756                 idx = helper->unmanaged_call_conv - 1;
3757         } else {
3758                 /* Managed */
3759                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3760                 if (helper->call_conv & 0x02) /* varargs */
3761                         idx += 0x05;
3762         }
3763
3764         sigbuffer_add_byte (&buf, idx);
3765         sigbuffer_add_value (&buf, nargs);
3766         encode_reflection_type (assembly, helper->return_type, &buf, error);
3767         if (!is_ok (error))
3768                 goto fail;
3769         for (i = 0; i < nargs; ++i) {
3770                 MonoArray *modreqs = NULL;
3771                 MonoArray *modopts = NULL;
3772                 MonoReflectionType *pt;
3773
3774                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3775                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3776                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3777                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3778
3779                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3780                 if (!is_ok (error))
3781                         goto fail;
3782                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3783                 encode_reflection_type (assembly, pt, &buf, error);
3784                 if (!is_ok (error))
3785                         goto fail;
3786         }
3787         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3788         sigbuffer_free (&buf);
3789
3790         return idx;
3791 fail:
3792         sigbuffer_free (&buf);
3793         return 0;
3794 }
3795
3796 static guint32 
3797 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3798 {
3799         guint32 idx;
3800         MonoDynamicTable *table;
3801         guint32 *values;
3802
3803         mono_error_init (error);
3804
3805         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3806         idx = table->next_idx ++;
3807         table->rows ++;
3808         alloc_table (table, table->rows);
3809         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3810
3811         values [MONO_STAND_ALONE_SIGNATURE] =
3812                 mono_reflection_encode_sighelper (assembly, helper, error);
3813         return_val_if_nok (error, 0);
3814         
3815         return idx;
3816 }
3817
3818 static int
3819 reflection_cc_to_file (int call_conv) {
3820         switch (call_conv & 0x3) {
3821         case 0:
3822         case 1: return MONO_CALL_DEFAULT;
3823         case 2: return MONO_CALL_VARARG;
3824         default:
3825                 g_assert_not_reached ();
3826         }
3827         return 0;
3828 }
3829 #endif /* !DISABLE_REFLECTION_EMIT */
3830
3831 typedef struct {
3832         MonoType *parent;
3833         MonoMethodSignature *sig;
3834         char *name;
3835         guint32 token;
3836 } ArrayMethod;
3837
3838 #ifndef DISABLE_REFLECTION_EMIT
3839 static guint32
3840 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3841 {
3842         guint32 nparams, i;
3843         GList *tmp;
3844         char *name = NULL;
3845         MonoMethodSignature *sig;
3846         ArrayMethod *am = NULL;
3847         MonoType *mtype;
3848
3849         mono_error_init (error);
3850
3851         nparams = mono_array_length (m->parameters);
3852         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3853         sig->hasthis = 1;
3854         sig->sentinelpos = -1;
3855         sig->call_convention = reflection_cc_to_file (m->call_conv);
3856         sig->param_count = nparams;
3857         if (m->ret) {
3858                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3859                 if (!is_ok (error))
3860                         goto fail;
3861         } else
3862                 sig->ret = &mono_defaults.void_class->byval_arg;
3863
3864         mtype = mono_reflection_type_get_handle (m->parent, error);
3865         if (!is_ok (error))
3866                 goto fail;
3867
3868         for (i = 0; i < nparams; ++i) {
3869                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3870                 if (!is_ok (error))
3871                         goto fail;
3872         }
3873
3874         name = mono_string_to_utf8 (m->name);
3875         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3876                 am = (ArrayMethod *)tmp->data;
3877                 if (strcmp (name, am->name) == 0 && 
3878                                 mono_metadata_type_equal (am->parent, mtype) &&
3879                                 mono_metadata_signature_equal (am->sig, sig)) {
3880                         g_free (name);
3881                         g_free (sig);
3882                         m->table_idx = am->token & 0xffffff;
3883                         return am->token;
3884                 }
3885         }
3886         am = g_new0 (ArrayMethod, 1);
3887         am->name = name;
3888         am->sig = sig;
3889         am->parent = mtype;
3890         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3891                 method_encode_signature (assembly, sig));
3892         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3893         m->table_idx = am->token & 0xffffff;
3894         return am->token;
3895 fail:
3896         g_free (am);
3897         g_free (name);
3898         g_free (sig);
3899         return 0;
3900
3901 }
3902
3903 /*
3904  * Insert into the metadata tables all the info about the TypeBuilder tb.
3905  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3906  */
3907 static gboolean
3908 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3909 {
3910         MonoDynamicTable *table;
3911         guint *values;
3912         int i, is_object = 0, is_system = 0;
3913         char *n;
3914
3915         mono_error_init (error);
3916
3917         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3918         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3919         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3920         n = mono_string_to_utf8 (tb->name);
3921         if (strcmp (n, "Object") == 0)
3922                 is_object++;
3923         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3924         g_free (n);
3925         n = mono_string_to_utf8 (tb->nspace);
3926         if (strcmp (n, "System") == 0)
3927                 is_system++;
3928         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3929         g_free (n);
3930         if (tb->parent && !(is_system && is_object) && 
3931                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3932                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3933                 return_val_if_nok (error, FALSE);
3934                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3935         } else {
3936                 values [MONO_TYPEDEF_EXTENDS] = 0;
3937         }
3938         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3939         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3940
3941         /*
3942          * if we have explicitlayout or sequentiallayouts, output data in the
3943          * ClassLayout table.
3944          */
3945         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3946                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3947                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3948                 table->rows++;
3949                 alloc_table (table, table->rows);
3950                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3951                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3952                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3953                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3954         }
3955
3956         /* handle interfaces */
3957         if (tb->interfaces) {
3958                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3959                 i = table->rows;
3960                 table->rows += mono_array_length (tb->interfaces);
3961                 alloc_table (table, table->rows);
3962                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3963                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3964                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3965                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3966                         return_val_if_nok (error, FALSE);
3967                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3968                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3969                         values += MONO_INTERFACEIMPL_SIZE;
3970                 }
3971         }
3972
3973         /* handle fields */
3974         if (tb->fields) {
3975                 table = &assembly->tables [MONO_TABLE_FIELD];
3976                 table->rows += tb->num_fields;
3977                 alloc_table (table, table->rows);
3978                 for (i = 0; i < tb->num_fields; ++i) {
3979                         mono_image_get_field_info (
3980                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3981                         return_val_if_nok (error, FALSE);
3982                 }
3983         }
3984
3985         /* handle constructors */
3986         if (tb->ctors) {
3987                 table = &assembly->tables [MONO_TABLE_METHOD];
3988                 table->rows += mono_array_length (tb->ctors);
3989                 alloc_table (table, table->rows);
3990                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3991                         if (!mono_image_get_ctor_info (domain,
3992                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3993                                                        assembly, error))
3994                                 return FALSE;
3995                 }
3996         }
3997
3998         /* handle methods */
3999         if (tb->methods) {
4000                 table = &assembly->tables [MONO_TABLE_METHOD];
4001                 table->rows += tb->num_methods;
4002                 alloc_table (table, table->rows);
4003                 for (i = 0; i < tb->num_methods; ++i) {
4004                         if (!mono_image_get_method_info (
4005                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4006                                 return FALSE;
4007                 }
4008         }
4009
4010         /* Do the same with properties etc.. */
4011         if (tb->events && mono_array_length (tb->events)) {
4012                 table = &assembly->tables [MONO_TABLE_EVENT];
4013                 table->rows += mono_array_length (tb->events);
4014                 alloc_table (table, table->rows);
4015                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4016                 table->rows ++;
4017                 alloc_table (table, table->rows);
4018                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4019                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4020                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4021                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4022                         mono_image_get_event_info (
4023                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4024                         return_val_if_nok (error, FALSE);
4025                 }
4026         }
4027         if (tb->properties && mono_array_length (tb->properties)) {
4028                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4029                 table->rows += mono_array_length (tb->properties);
4030                 alloc_table (table, table->rows);
4031                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4032                 table->rows ++;
4033                 alloc_table (table, table->rows);
4034                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4035                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4036                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4037                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4038                         mono_image_get_property_info (
4039                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4040                         return_val_if_nok (error, FALSE);
4041                 }
4042         }
4043
4044         /* handle generic parameters */
4045         if (tb->generic_params) {
4046                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4047                 table->rows += mono_array_length (tb->generic_params);
4048                 alloc_table (table, table->rows);
4049                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4050                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4051
4052                         mono_image_get_generic_param_info (
4053                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4054                 }
4055         }
4056
4057         mono_image_add_decl_security (assembly, 
4058                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4059
4060         if (tb->subtypes) {
4061                 MonoDynamicTable *ntable;
4062                 
4063                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4064                 ntable->rows += mono_array_length (tb->subtypes);
4065                 alloc_table (ntable, ntable->rows);
4066                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4067
4068                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4069                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4070
4071                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4072                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4073                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4074                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4075                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4076                                 ntable->next_idx, ntable->rows);*/
4077                         values += MONO_NESTED_CLASS_SIZE;
4078                         ntable->next_idx++;
4079                 }
4080         }
4081
4082         return TRUE;
4083 }
4084 #endif
4085
4086 static void
4087 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4088 {
4089         int i;
4090
4091         mono_ptr_array_append (*types, type);
4092
4093         if (!type->subtypes)
4094                 return;
4095
4096         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4097                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4098                 collect_types (types, subtype);
4099         }
4100 }
4101
4102 static gint
4103 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4104 {
4105         if ((*type1)->table_idx < (*type2)->table_idx)
4106                 return -1;
4107         else
4108                 if ((*type1)->table_idx > (*type2)->table_idx)
4109                         return 1;
4110         else
4111                 return 0;
4112 }
4113
4114 static gboolean
4115 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4116         int i;
4117
4118         mono_error_init (error);
4119         if (!pinfo)
4120                 return TRUE;
4121         for (i = 0; i < mono_array_length (pinfo); ++i) {
4122                 MonoReflectionParamBuilder *pb;
4123                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4124                 if (!pb)
4125                         continue;
4126                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4127                         return FALSE;
4128         }
4129
4130         return TRUE;
4131 }
4132
4133 static gboolean
4134 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4135         int i;
4136
4137         mono_error_init (error);
4138         
4139         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4140                 return FALSE;
4141         if (tb->fields) {
4142                 for (i = 0; i < tb->num_fields; ++i) {
4143                         MonoReflectionFieldBuilder* fb;
4144                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4145                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4146                                 return FALSE;
4147                 }
4148         }
4149         if (tb->events) {
4150                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4151                         MonoReflectionEventBuilder* eb;
4152                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4153                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4154                                 return FALSE;
4155                 }
4156         }
4157         if (tb->properties) {
4158                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4159                         MonoReflectionPropertyBuilder* pb;
4160                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4161                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4162                                 return FALSE;
4163                 }
4164         }
4165         if (tb->ctors) {
4166                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4167                         MonoReflectionCtorBuilder* cb;
4168                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4169                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4170                             !params_add_cattrs (assembly, cb->pinfo, error))
4171                                 return FALSE;
4172                 }
4173         }
4174
4175         if (tb->methods) {
4176                 for (i = 0; i < tb->num_methods; ++i) {
4177                         MonoReflectionMethodBuilder* mb;
4178                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4179                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4180                             !params_add_cattrs (assembly, mb->pinfo, error))
4181                                 return FALSE;
4182                 }
4183         }
4184
4185         if (tb->subtypes) {
4186                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4187                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4188                                 return FALSE;
4189                 }
4190         }
4191
4192         return TRUE;
4193 }
4194
4195 static gboolean
4196 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4197 {
4198         int i;
4199         
4200         mono_error_init (error);
4201
4202         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4203                 return FALSE;
4204
4205         if (moduleb->global_methods) {
4206                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4207                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4208                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4209                             !params_add_cattrs (assembly, mb->pinfo, error))
4210                                 return FALSE;
4211                 }
4212         }
4213
4214         if (moduleb->global_fields) {
4215                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4216                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4217                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4218                                 return FALSE;
4219                 }
4220         }
4221         
4222         if (moduleb->types) {
4223                 for (i = 0; i < moduleb->num_types; ++i) {
4224                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4225                                 return FALSE;
4226                 }
4227         }
4228
4229         return TRUE;
4230 }
4231
4232 static void
4233 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4234 {
4235         MonoDynamicTable *table;
4236         guint32 *values;
4237         char blob_size [6];
4238         guchar hash [20];
4239         char *b = blob_size;
4240         char *dir, *path;
4241
4242         table = &assembly->tables [MONO_TABLE_FILE];
4243         table->rows++;
4244         alloc_table (table, table->rows);
4245         values = table->values + table->next_idx * MONO_FILE_SIZE;
4246         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4247         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4248         if (image_is_dynamic (module->image)) {
4249                 /* This depends on the fact that the main module is emitted last */
4250                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4251                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4252         } else {
4253                 dir = NULL;
4254                 path = g_strdup (module->image->name);
4255         }
4256         mono_sha1_get_digest_from_file (path, hash);
4257         g_free (dir);
4258         g_free (path);
4259         mono_metadata_encode_value (20, b, &b);
4260         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4261         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4262         table->next_idx ++;
4263 }
4264
4265 static void
4266 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4267 {
4268         MonoDynamicTable *table;
4269         int i;
4270
4271         table = &assembly->tables [MONO_TABLE_MODULE];
4272         mb->table_idx = table->next_idx ++;
4273         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4274         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4275         i /= 16;
4276         ++i;
4277         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4278         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4279         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4280         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4281 }
4282
4283 static guint32
4284 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4285         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4286 {
4287         MonoDynamicTable *table;
4288         guint32 *values;
4289         guint32 visib, res;
4290
4291         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4292         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4293                 return 0;
4294
4295         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4296         table->rows++;
4297         alloc_table (table, table->rows);
4298         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4299
4300         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4301         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4302         if (klass->nested_in)
4303                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4304         else
4305                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4306         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4307         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4308
4309         res = table->next_idx;
4310
4311         table->next_idx ++;
4312
4313         /* Emit nested types */
4314         if (klass->ext && klass->ext->nested_classes) {
4315                 GList *tmp;
4316
4317                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4318                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4319         }
4320
4321         return res;
4322 }
4323
4324 static void
4325 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4326                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4327                               MonoError *error)
4328 {
4329         MonoClass *klass;
4330         guint32 idx, i;
4331
4332         mono_error_init (error);
4333
4334         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4335         return_if_nok (error);
4336
4337         klass = mono_class_from_mono_type (t);
4338
4339         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4340
4341         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4342                                                                                                    parent_index, assembly);
4343
4344         /* 
4345          * Emit nested types
4346          * We need to do this ourselves since klass->nested_classes is not set up.
4347          */
4348         if (tb->subtypes) {
4349                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4350                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4351                         return_if_nok (error);
4352                 }
4353         }
4354 }
4355
4356 static void
4357 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4358         guint32 module_index, MonoDynamicImage *assembly)
4359 {
4360         MonoImage *image = module->image;
4361         MonoTableInfo  *t;
4362         guint32 i;
4363
4364         t = &image->tables [MONO_TABLE_TYPEDEF];
4365
4366         for (i = 0; i < t->rows; ++i) {
4367                 MonoError error;
4368                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4369                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4370
4371                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4372                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4373         }
4374 }
4375
4376 static void
4377 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4378 {
4379         MonoDynamicTable *table;
4380         guint32 *values;
4381         guint32 scope, scope_idx, impl, current_idx;
4382         gboolean forwarder = TRUE;
4383         gpointer iter = NULL;
4384         MonoClass *nested;
4385
4386         if (klass->nested_in) {
4387                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4388                 forwarder = FALSE;
4389         } else {
4390                 scope = resolution_scope_from_image (assembly, klass->image);
4391                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4392                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4393                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4394         }
4395
4396         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4397
4398         table->rows++;
4399         alloc_table (table, table->rows);
4400         current_idx = table->next_idx;
4401         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4402
4403         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4404         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4405         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4406         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4407         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4408
4409         table->next_idx++;
4410
4411         while ((nested = mono_class_get_nested_types (klass, &iter)))
4412                 add_exported_type (assemblyb, assembly, nested, current_idx);
4413 }
4414
4415 static void
4416 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4417 {
4418         MonoError error;
4419         MonoClass *klass;
4420         int i;
4421
4422         if (!assemblyb->type_forwarders)
4423                 return;
4424
4425         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4426                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4427                 MonoType *type;
4428                 if (!t)
4429                         continue;
4430
4431                 type = mono_reflection_type_get_handle (t, &error);
4432                 mono_error_assert_ok (&error);
4433                 g_assert (type);
4434
4435                 klass = mono_class_from_mono_type (type);
4436
4437                 add_exported_type (assemblyb, assembly, klass, 0);
4438         }
4439 }
4440
4441 #define align_pointer(base,p)\
4442         do {\
4443                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4444                 if (__diff & 3)\
4445                         (p) += 4 - (__diff & 3);\
4446         } while (0)
4447
4448 static int
4449 compare_constants (const void *a, const void *b)
4450 {
4451         const guint32 *a_values = (const guint32 *)a;
4452         const guint32 *b_values = (const guint32 *)b;
4453         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4454 }
4455
4456 static int
4457 compare_semantics (const void *a, const void *b)
4458 {
4459         const guint32 *a_values = (const guint32 *)a;
4460         const guint32 *b_values = (const guint32 *)b;
4461         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4462         if (assoc)
4463                 return assoc;
4464         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4465 }
4466
4467 static int
4468 compare_custom_attrs (const void *a, const void *b)
4469 {
4470         const guint32 *a_values = (const guint32 *)a;
4471         const guint32 *b_values = (const guint32 *)b;
4472
4473         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4474 }
4475
4476 static int
4477 compare_field_marshal (const void *a, const void *b)
4478 {
4479         const guint32 *a_values = (const guint32 *)a;
4480         const guint32 *b_values = (const guint32 *)b;
4481
4482         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4483 }
4484
4485 static int
4486 compare_nested (const void *a, const void *b)
4487 {
4488         const guint32 *a_values = (const guint32 *)a;
4489         const guint32 *b_values = (const guint32 *)b;
4490
4491         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4492 }
4493
4494 static int
4495 compare_genericparam (const void *a, const void *b)
4496 {
4497         MonoError error;
4498         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4499         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4500
4501         if ((*b_entry)->owner == (*a_entry)->owner) {
4502                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4503                 mono_error_assert_ok (&error);
4504                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4505                 mono_error_assert_ok (&error);
4506                 return 
4507                         mono_type_get_generic_param_num (a_type) -
4508                         mono_type_get_generic_param_num (b_type);
4509         } else
4510                 return (*a_entry)->owner - (*b_entry)->owner;
4511 }
4512
4513 static int
4514 compare_declsecurity_attrs (const void *a, const void *b)
4515 {
4516         const guint32 *a_values = (const guint32 *)a;
4517         const guint32 *b_values = (const guint32 *)b;
4518
4519         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4520 }
4521
4522 static int
4523 compare_interface_impl (const void *a, const void *b)
4524 {
4525         const guint32 *a_values = (const guint32 *)a;
4526         const guint32 *b_values = (const guint32 *)b;
4527
4528         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4529         if (klass)
4530                 return klass;
4531
4532         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4533 }
4534
4535 static void
4536 pad_heap (MonoDynamicStream *sh)
4537 {
4538         if (sh->index & 3) {
4539                 int sz = 4 - (sh->index & 3);
4540                 memset (sh->data + sh->index, 0, sz);
4541                 sh->index += sz;
4542         }
4543 }
4544
4545 struct StreamDesc {
4546         const char *name;
4547         MonoDynamicStream *stream;
4548 };
4549
4550 /*
4551  * build_compressed_metadata() fills in the blob of data that represents the 
4552  * raw metadata as it will be saved in the PE file. The five streams are output 
4553  * and the metadata tables are comnpressed from the guint32 array representation, 
4554  * to the compressed on-disk format.
4555  */
4556 static gboolean
4557 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4558 {
4559         MonoDynamicTable *table;
4560         int i;
4561         guint64 valid_mask = 0;
4562         guint64 sorted_mask;
4563         guint32 heapt_size = 0;
4564         guint32 meta_size = 256; /* allow for header and other stuff */
4565         guint32 table_offset;
4566         guint32 ntables = 0;
4567         guint64 *int64val;
4568         guint32 *int32val;
4569         guint16 *int16val;
4570         MonoImage *meta;
4571         unsigned char *p;
4572         struct StreamDesc stream_desc [5];
4573
4574         mono_error_init (error);
4575
4576         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4577         for (i = 0; i < assembly->gen_params->len; i++) {
4578                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4579                 if (!write_generic_param_entry (assembly, entry, error))
4580                         return FALSE;
4581         }
4582
4583         stream_desc [0].name  = "#~";
4584         stream_desc [0].stream = &assembly->tstream;
4585         stream_desc [1].name  = "#Strings";
4586         stream_desc [1].stream = &assembly->sheap;
4587         stream_desc [2].name  = "#US";
4588         stream_desc [2].stream = &assembly->us;
4589         stream_desc [3].name  = "#Blob";
4590         stream_desc [3].stream = &assembly->blob;
4591         stream_desc [4].name  = "#GUID";
4592         stream_desc [4].stream = &assembly->guid;
4593         
4594         /* tables that are sorted */
4595         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4596                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4597                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4598                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4599                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4600                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4601                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4602         
4603         /* Compute table sizes */
4604         /* the MonoImage has already been created in mono_image_basic_init() */
4605         meta = &assembly->image;
4606
4607         /* sizes should be multiple of 4 */
4608         pad_heap (&assembly->blob);
4609         pad_heap (&assembly->guid);
4610         pad_heap (&assembly->sheap);
4611         pad_heap (&assembly->us);
4612
4613         /* Setup the info used by compute_sizes () */
4614         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4615         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4616         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4617
4618         meta_size += assembly->blob.index;
4619         meta_size += assembly->guid.index;
4620         meta_size += assembly->sheap.index;
4621         meta_size += assembly->us.index;
4622
4623         for (i=0; i < MONO_TABLE_NUM; ++i)
4624                 meta->tables [i].rows = assembly->tables [i].rows;
4625         
4626         for (i = 0; i < MONO_TABLE_NUM; i++){
4627                 if (meta->tables [i].rows == 0)
4628                         continue;
4629                 valid_mask |= (guint64)1 << i;
4630                 ntables ++;
4631                 meta->tables [i].row_size = mono_metadata_compute_size (
4632                         meta, i, &meta->tables [i].size_bitfield);
4633                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4634         }
4635         heapt_size += 24; /* #~ header size */
4636         heapt_size += ntables * 4;
4637         /* make multiple of 4 */
4638         heapt_size += 3;
4639         heapt_size &= ~3;
4640         meta_size += heapt_size;
4641         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4642         p = (unsigned char*)meta->raw_metadata;
4643         /* the metadata signature */
4644         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4645         /* version numbers and 4 bytes reserved */
4646         int16val = (guint16*)p;
4647         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4648         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4649         p += 8;
4650         /* version string */
4651         int32val = (guint32*)p;
4652         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4653         p += 4;
4654         memcpy (p, meta->version, strlen (meta->version));
4655         p += GUINT32_FROM_LE (*int32val);
4656         align_pointer (meta->raw_metadata, p);
4657         int16val = (guint16*)p;
4658         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4659         *int16val = GUINT16_TO_LE (5); /* number of streams */
4660         p += 4;
4661
4662         /*
4663          * write the stream info.
4664          */
4665         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4666         table_offset += 3; table_offset &= ~3;
4667
4668         assembly->tstream.index = heapt_size;
4669         for (i = 0; i < 5; ++i) {
4670                 int32val = (guint32*)p;
4671                 stream_desc [i].stream->offset = table_offset;
4672                 *int32val++ = GUINT32_TO_LE (table_offset);
4673                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4674                 table_offset += GUINT32_FROM_LE (*int32val);
4675                 table_offset += 3; table_offset &= ~3;
4676                 p += 8;
4677                 strcpy ((char*)p, stream_desc [i].name);
4678                 p += strlen (stream_desc [i].name) + 1;
4679                 align_pointer (meta->raw_metadata, p);
4680         }
4681         /* 
4682          * now copy the data, the table stream header and contents goes first.
4683          */
4684         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4685         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4686         int32val = (guint32*)p;
4687         *int32val = GUINT32_TO_LE (0); /* reserved */
4688         p += 4;
4689
4690         *p++ = 2; /* version */
4691         *p++ = 0;
4692
4693         if (meta->idx_string_wide)
4694                 *p |= 0x01;
4695         if (meta->idx_guid_wide)
4696                 *p |= 0x02;
4697         if (meta->idx_blob_wide)
4698                 *p |= 0x04;
4699         ++p;
4700         *p++ = 1; /* reserved */
4701         int64val = (guint64*)p;
4702         *int64val++ = GUINT64_TO_LE (valid_mask);
4703         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4704         p += 16;
4705         int32val = (guint32*)p;
4706         for (i = 0; i < MONO_TABLE_NUM; i++){
4707                 if (meta->tables [i].rows == 0)
4708                         continue;
4709                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4710         }
4711         p = (unsigned char*)int32val;
4712
4713         /* sort the tables that still need sorting */
4714         table = &assembly->tables [MONO_TABLE_CONSTANT];
4715         if (table->rows)
4716                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4717         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4718         if (table->rows)
4719                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4720         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4721         if (table->rows)
4722                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4723         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4724         if (table->rows)
4725                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4726         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4727         if (table->rows)
4728                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4729         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4730         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4731         if (table->rows)
4732                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4733         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4734         if (table->rows)
4735                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4736
4737         /* compress the tables */
4738         for (i = 0; i < MONO_TABLE_NUM; i++){
4739                 int row, col;
4740                 guint32 *values;
4741                 guint32 bitfield = meta->tables [i].size_bitfield;
4742                 if (!meta->tables [i].rows)
4743                         continue;
4744                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4745                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4746                 meta->tables [i].base = (char*)p;
4747                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4748                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4749                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4750                                 switch (mono_metadata_table_size (bitfield, col)) {
4751                                 case 1:
4752                                         *p++ = values [col];
4753                                         break;
4754                                 case 2:
4755                                         *p++ = values [col] & 0xff;
4756                                         *p++ = (values [col] >> 8) & 0xff;
4757                                         break;
4758                                 case 4:
4759                                         *p++ = values [col] & 0xff;
4760                                         *p++ = (values [col] >> 8) & 0xff;
4761                                         *p++ = (values [col] >> 16) & 0xff;
4762                                         *p++ = (values [col] >> 24) & 0xff;
4763                                         break;
4764                                 default:
4765                                         g_assert_not_reached ();
4766                                 }
4767                         }
4768                 }
4769                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4770         }
4771         
4772         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4773         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4774         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4775         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4776         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4777
4778         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4779
4780         return TRUE;
4781 }
4782
4783 /*
4784  * Some tables in metadata need to be sorted according to some criteria, but
4785  * when methods and fields are first created with reflection, they may be assigned a token
4786  * that doesn't correspond to the final token they will get assigned after the sorting.
4787  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4788  * with the reflection objects that represent them. Once all the tables are set up, the 
4789  * reflection objects will contains the correct table index. fixup_method() will fixup the
4790  * tokens for the method with ILGenerator @ilgen.
4791  */
4792 static void
4793 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4794 {
4795         guint32 code_idx = GPOINTER_TO_UINT (value);
4796         MonoReflectionILTokenInfo *iltoken;
4797         MonoReflectionFieldBuilder *field;
4798         MonoReflectionCtorBuilder *ctor;
4799         MonoReflectionMethodBuilder *method;
4800         MonoReflectionTypeBuilder *tb;
4801         MonoReflectionArrayMethod *am;
4802         guint32 i, idx = 0;
4803         unsigned char *target;
4804
4805         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4806                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4807                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4808                 switch (target [3]) {
4809                 case MONO_TABLE_FIELD:
4810                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4811                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4812                                 idx = field->table_idx;
4813                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4814                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4815                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4816                         } else {
4817                                 g_assert_not_reached ();
4818                         }
4819                         break;
4820                 case MONO_TABLE_METHOD:
4821                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4822                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4823                                 idx = method->table_idx;
4824                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4825                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4826                                 idx = ctor->table_idx;
4827                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4828                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4829                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4830                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4831                         } else {
4832                                 g_assert_not_reached ();
4833                         }
4834                         break;
4835                 case MONO_TABLE_TYPEDEF:
4836                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4837                                 g_assert_not_reached ();
4838                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4839                         idx = tb->table_idx;
4840                         break;
4841                 case MONO_TABLE_MEMBERREF:
4842                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4843                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4844                                 idx = am->table_idx;
4845                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4846                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4847                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4848                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4849                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4850                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4851                                 continue;
4852                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4853                                 continue;
4854                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4855                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4856                                 g_assert (is_field_on_inst (f));
4857                                 continue;
4858                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4859                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4860                                 continue;
4861                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4862                                 continue;
4863                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4864                                 continue;
4865                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4866                                 continue;
4867                         } else {
4868                                 g_assert_not_reached ();
4869                         }
4870                         break;
4871                 case MONO_TABLE_METHODSPEC:
4872                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4873                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4874                                 g_assert (mono_method_signature (m)->generic_param_count);
4875                                 continue;
4876                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4877                                 continue;
4878                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4879                                 continue;
4880                         } else {
4881                                 g_assert_not_reached ();
4882                         }
4883                         break;
4884                 default:
4885                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4886                 }
4887                 target [0] = idx & 0xff;
4888                 target [1] = (idx >> 8) & 0xff;
4889                 target [2] = (idx >> 16) & 0xff;
4890         }
4891 }
4892
4893 /*
4894  * fixup_cattrs:
4895  *
4896  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4897  * value is not known when the table is emitted.
4898  */
4899 static void
4900 fixup_cattrs (MonoDynamicImage *assembly)
4901 {
4902         MonoDynamicTable *table;
4903         guint32 *values;
4904         guint32 type, i, idx, token;
4905         MonoObject *ctor;
4906
4907         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4908
4909         for (i = 0; i < table->rows; ++i) {
4910                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4911
4912                 type = values [MONO_CUSTOM_ATTR_TYPE];
4913                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4914                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4915                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4916                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4917                         g_assert (ctor);
4918
4919                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4920                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4921                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4922                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4923                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4924                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4925                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4926                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4927                         }
4928                 }
4929         }
4930 }
4931
4932 static void
4933 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4934 {
4935         MonoDynamicTable *table;
4936         guint32 *values;
4937
4938         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4939         table->rows++;
4940         alloc_table (table, table->rows);
4941         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4942         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4943         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4944         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4945         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4946         table->next_idx++;
4947 }
4948
4949 static void
4950 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4951 {
4952         MonoDynamicTable *table;
4953         guint32 *values;
4954         char blob_size [6];
4955         guchar hash [20];
4956         char *b = blob_size;
4957         char *name, *sname;
4958         guint32 idx, offset;
4959
4960         if (rsrc->filename) {
4961                 name = mono_string_to_utf8 (rsrc->filename);
4962                 sname = g_path_get_basename (name);
4963         
4964                 table = &assembly->tables [MONO_TABLE_FILE];
4965                 table->rows++;
4966                 alloc_table (table, table->rows);
4967                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4968                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4969                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4970                 g_free (sname);
4971
4972                 mono_sha1_get_digest_from_file (name, hash);
4973                 mono_metadata_encode_value (20, b, &b);
4974                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4975                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4976                 g_free (name);
4977                 idx = table->next_idx++;
4978                 rsrc->offset = 0;
4979                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4980         } else {
4981                 char sizebuf [4];
4982                 char *data;
4983                 guint len;
4984                 if (rsrc->data) {
4985                         data = mono_array_addr (rsrc->data, char, 0);
4986                         len = mono_array_length (rsrc->data);
4987                 } else {
4988                         data = NULL;
4989                         len = 0;
4990                 }
4991                 offset = len;
4992                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4993                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4994                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4995                 mono_image_add_stream_data (&assembly->resources, data, len);
4996
4997                 if (!mb->is_main)
4998                         /* 
4999                          * The entry should be emitted into the MANIFESTRESOURCE table of 
5000                          * the main module, but that needs to reference the FILE table
5001                          * which isn't emitted yet.
5002                          */
5003                         return;
5004                 else
5005                         idx = 0;
5006         }
5007
5008         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5009 }
5010
5011 static void
5012 set_version_from_string (MonoString *version, guint32 *values)
5013 {
5014         gchar *ver, *p, *str;
5015         guint32 i;
5016         
5017         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5018         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5019         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5020         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5021         if (!version)
5022                 return;
5023         ver = str = mono_string_to_utf8 (version);
5024         for (i = 0; i < 4; ++i) {
5025                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5026                 switch (*p) {
5027                 case '.':
5028                         p++;
5029                         break;
5030                 case '*':
5031                         /* handle Revision and Build */
5032                         p++;
5033                         break;
5034                 }
5035                 ver = p;
5036         }
5037         g_free (str);
5038 }
5039
5040 static guint32
5041 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5042         gsize len;
5043         guint32 token = 0;
5044         char blob_size [6];
5045         char *b = blob_size;
5046
5047         if (!pkey)
5048                 return token;
5049
5050         len = mono_array_length (pkey);
5051         mono_metadata_encode_value (len, b, &b);
5052         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5053         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5054
5055         assembly->public_key = (guint8 *)g_malloc (len);
5056         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5057         assembly->public_key_len = len;
5058
5059         /* Special case: check for ECMA key (16 bytes) */
5060         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5061                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5062                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5063         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5064                 /* minimum key size (in 2.0) is 384 bits */
5065                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5066         } else {
5067                 /* FIXME - verifier */
5068                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5069                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5070         }
5071         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5072
5073         return token;
5074 }
5075
5076 static void
5077 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5078 {
5079         MonoDynamicTable *table;
5080         MonoDynamicImage *assembly;
5081         MonoReflectionAssemblyBuilder *assemblyb;
5082         MonoDomain *domain;
5083         guint32 *values;
5084         int i;
5085         guint32 module_index;
5086
5087         mono_error_init (error);
5088
5089         assemblyb = moduleb->assemblyb;
5090         assembly = moduleb->dynamic_image;
5091         domain = mono_object_domain (assemblyb);
5092
5093         /* Emit ASSEMBLY table */
5094         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5095         alloc_table (table, 1);
5096         values = table->values + MONO_ASSEMBLY_SIZE;
5097         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5098         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5099         if (assemblyb->culture) {
5100                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5101         } else {
5102                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5103         }
5104         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5105         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5106         set_version_from_string (assemblyb->version, values);
5107
5108         /* Emit FILE + EXPORTED_TYPE table */
5109         module_index = 0;
5110         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5111                 int j;
5112                 MonoReflectionModuleBuilder *file_module = 
5113                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5114                 if (file_module != moduleb) {
5115                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5116                         module_index ++;
5117                         if (file_module->types) {
5118                                 for (j = 0; j < file_module->num_types; ++j) {
5119                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5120                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, error);
5121                                         return_if_nok (error);
5122                                 }
5123                         }
5124                 }
5125         }
5126         if (assemblyb->loaded_modules) {
5127                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5128                         MonoReflectionModule *file_module = 
5129                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5130                         mono_image_fill_file_table (domain, file_module, assembly);
5131                         module_index ++;
5132                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5133                 }
5134         }
5135         if (assemblyb->type_forwarders)
5136                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5137
5138         /* Emit MANIFESTRESOURCE table */
5139         module_index = 0;
5140         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5141                 int j;
5142                 MonoReflectionModuleBuilder *file_module = 
5143                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5144                 /* The table for the main module is emitted later */
5145                 if (file_module != moduleb) {
5146                         module_index ++;
5147                         if (file_module->resources) {
5148                                 int len = mono_array_length (file_module->resources);
5149                                 for (j = 0; j < len; ++j) {
5150                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5151                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5152                                 }
5153                         }
5154                 }
5155         }               
5156 }
5157
5158 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5159
5160 /*
5161  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5162  * for the modulebuilder @moduleb.
5163  * At the end of the process, method and field tokens are fixed up and the 
5164  * on-disk compressed metadata representation is created.
5165  * Return TRUE on success, or FALSE on failure and sets @error
5166  */
5167 gboolean
5168 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5169 {
5170         MonoDynamicTable *table;
5171         MonoDynamicImage *assembly;
5172         MonoReflectionAssemblyBuilder *assemblyb;
5173         MonoDomain *domain;
5174         MonoPtrArray types;
5175         guint32 *values;
5176         int i, j;
5177
5178         mono_error_init (error);
5179
5180         assemblyb = moduleb->assemblyb;
5181         assembly = moduleb->dynamic_image;
5182         domain = mono_object_domain (assemblyb);
5183
5184         if (assembly->text_rva)
5185                 return TRUE;
5186
5187         assembly->text_rva = START_TEXT_RVA;
5188
5189         if (moduleb->is_main) {
5190                 mono_image_emit_manifest (moduleb, error);
5191                 return_val_if_nok (error, FALSE);
5192         }
5193
5194         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5195         table->rows = 1; /* .<Module> */
5196         table->next_idx++;
5197         alloc_table (table, table->rows);
5198         /*
5199          * Set the first entry.
5200          */
5201         values = table->values + table->columns;
5202         values [MONO_TYPEDEF_FLAGS] = 0;
5203         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5204         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5205         values [MONO_TYPEDEF_EXTENDS] = 0;
5206         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5207         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5208
5209         /* 
5210          * handle global methods 
5211          * FIXME: test what to do when global methods are defined in multiple modules.
5212          */
5213         if (moduleb->global_methods) {
5214                 table = &assembly->tables [MONO_TABLE_METHOD];
5215                 table->rows += mono_array_length (moduleb->global_methods);
5216                 alloc_table (table, table->rows);
5217                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5218                         if (!mono_image_get_method_info (
5219                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5220                                 goto leave;
5221                 }
5222         }
5223         if (moduleb->global_fields) {
5224                 table = &assembly->tables [MONO_TABLE_FIELD];
5225                 table->rows += mono_array_length (moduleb->global_fields);
5226                 alloc_table (table, table->rows);
5227                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5228                         mono_image_get_field_info (
5229                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5230                                 error);
5231                         if (!is_ok (error))
5232                                 goto leave;
5233                 }
5234         }
5235
5236         table = &assembly->tables [MONO_TABLE_MODULE];
5237         alloc_table (table, 1);
5238         mono_image_fill_module_table (domain, moduleb, assembly);
5239
5240         /* Collect all types into a list sorted by their table_idx */
5241         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5242
5243         if (moduleb->types)
5244                 for (i = 0; i < moduleb->num_types; ++i) {
5245                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5246                         collect_types (&types, type);
5247                 }
5248
5249         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5250         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5251         table->rows += mono_ptr_array_size (types);
5252         alloc_table (table, table->rows);
5253
5254         /*
5255          * Emit type names + namespaces at one place inside the string heap,
5256          * so load_class_names () needs to touch fewer pages.
5257          */
5258         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5259                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5260                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5261         }
5262         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5263                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5264                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5265         }
5266
5267         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5268                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5269                 if (!mono_image_get_type_info (domain, type, assembly, error))
5270                         goto leave_types;
5271         }
5272
5273         /* 
5274          * table->rows is already set above and in mono_image_fill_module_table.
5275          */
5276         /* add all the custom attributes at the end, once all the indexes are stable */
5277         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5278                 goto leave_types;
5279
5280         /* CAS assembly permissions */
5281         if (assemblyb->permissions_minimum)
5282                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5283         if (assemblyb->permissions_optional)
5284                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5285         if (assemblyb->permissions_refused)
5286                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5287
5288         if (!module_add_cattrs (assembly, moduleb, error))
5289                 goto leave_types;
5290
5291         /* fixup tokens */
5292         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5293
5294         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5295          * the final tokens and don't need another fixup pass. */
5296
5297         if (moduleb->global_methods) {
5298                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5299                         MonoReflectionMethodBuilder *mb = mono_array_get (
5300                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5301                         if (!mono_image_add_methodimpl (assembly, mb, error))
5302                                 goto leave_types;
5303                 }
5304         }
5305
5306         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5307                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5308                 if (type->methods) {
5309                         for (j = 0; j < type->num_methods; ++j) {
5310                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5311                                         type->methods, MonoReflectionMethodBuilder*, j);
5312
5313                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5314                                         goto leave_types;
5315                         }
5316                 }
5317         }
5318
5319         fixup_cattrs (assembly);
5320
5321 leave_types:
5322         mono_ptr_array_destroy (types);
5323 leave:
5324
5325         return mono_error_ok (error);
5326 }
5327
5328 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5329
5330 gboolean
5331 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5332 {
5333         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5334 }
5335
5336 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5337
5338
5339 typedef struct {
5340         guint32 import_lookup_table;
5341         guint32 timestamp;
5342         guint32 forwarder;
5343         guint32 name_rva;
5344         guint32 import_address_table_rva;
5345 } MonoIDT;
5346
5347 typedef struct {
5348         guint32 name_rva;
5349         guint32 flags;
5350 } MonoILT;
5351
5352 #ifndef DISABLE_REFLECTION_EMIT
5353
5354 /*
5355  * mono_image_insert_string:
5356  * @module: module builder object
5357  * @str: a string
5358  *
5359  * Insert @str into the user string stream of @module.
5360  */
5361 guint32
5362 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5363 {
5364         MonoDynamicImage *assembly;
5365         guint32 idx;
5366         char buf [16];
5367         char *b = buf;
5368         
5369         if (!module->dynamic_image)
5370                 mono_image_module_basic_init (module);
5371
5372         assembly = module->dynamic_image;
5373         
5374         if (assembly->save) {
5375                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5376                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5377 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5378         {
5379                 char *swapped = g_malloc (2 * mono_string_length (str));
5380                 const char *p = (const char*)mono_string_chars (str);
5381
5382                 swap_with_size (swapped, p, 2, mono_string_length (str));
5383                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5384                 g_free (swapped);
5385         }
5386 #else
5387                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5388 #endif
5389                 mono_image_add_stream_data (&assembly->us, "", 1);
5390         } else {
5391                 idx = assembly->us.index ++;
5392         }
5393
5394         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5395
5396         return MONO_TOKEN_STRING | idx;
5397 }
5398
5399 guint32
5400 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5401 {
5402         MonoClass *klass;
5403         guint32 token = 0;
5404         MonoMethodSignature *sig;
5405
5406         mono_error_init (error);
5407
5408         klass = obj->vtable->klass;
5409         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5410                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5411                 MonoMethodSignature *old;
5412                 guint32 sig_token, parent;
5413                 int nargs, i;
5414
5415                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5416
5417                 nargs = mono_array_length (opt_param_types);
5418                 old = mono_method_signature (method);
5419                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5420
5421                 sig->hasthis = old->hasthis;
5422                 sig->explicit_this = old->explicit_this;
5423                 sig->call_convention = old->call_convention;
5424                 sig->generic_param_count = old->generic_param_count;
5425                 sig->param_count = old->param_count + nargs;
5426                 sig->sentinelpos = old->param_count;
5427                 sig->ret = old->ret;
5428
5429                 for (i = 0; i < old->param_count; i++)
5430                         sig->params [i] = old->params [i];
5431
5432                 for (i = 0; i < nargs; i++) {
5433                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5434                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5435                         if (!is_ok (error)) goto fail;
5436                 }
5437
5438                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5439                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5440                 parent >>= MONO_TYPEDEFORREF_BITS;
5441
5442                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5443                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5444
5445                 sig_token = method_encode_signature (assembly, sig);
5446                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5447         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5448                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5449                 ReflectionMethodBuilder rmb;
5450                 guint32 parent, sig_token;
5451                 int nopt_args, nparams, ngparams, i;
5452
5453                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5454                         goto fail;
5455                 
5456                 rmb.opt_types = opt_param_types;
5457                 nopt_args = mono_array_length (opt_param_types);
5458
5459                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5460                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5461                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5462
5463                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5464                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5465                 sig->call_convention = rmb.call_conv;
5466                 sig->generic_param_count = ngparams;
5467                 sig->param_count = nparams + nopt_args;
5468                 sig->sentinelpos = nparams;
5469                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5470                 if (!is_ok (error)) goto fail;
5471
5472                 for (i = 0; i < nparams; i++) {
5473                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5474                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5475                         if (!is_ok (error)) goto fail;
5476                 }
5477
5478                 for (i = 0; i < nopt_args; i++) {
5479                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5480                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5481                         if (!is_ok (error)) goto fail;
5482                 }
5483
5484                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5485                 if (!is_ok (error))
5486                         goto fail;
5487
5488                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5489                 if (!mono_error_ok (error))
5490                         goto fail;
5491                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5492
5493                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5494                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5495
5496                 char *name = mono_string_to_utf8 (rmb.name);
5497                 token = mono_image_get_varargs_method_token (
5498                         assembly, parent, name, sig_token);
5499                 g_free (name);
5500         } else {
5501                 g_error ("requested method token for %s\n", klass->name);
5502         }
5503
5504         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5505         register_dyn_token (assembly, token, obj);
5506         return token;
5507 fail:
5508         g_assert (!mono_error_ok (error));
5509         return 0;
5510 }
5511
5512 /*
5513  * mono_image_create_token:
5514  * @assembly: a dynamic assembly
5515  * @obj:
5516  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5517  *
5518  * Get a token to insert in the IL code stream for the given MemberInfo.
5519  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5520  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5521  * entry.
5522  */
5523 guint32
5524 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5525                          gboolean create_open_instance, gboolean register_token,
5526                          MonoError *error)
5527 {
5528         MonoClass *klass;
5529         guint32 token = 0;
5530
5531         mono_error_init (error);
5532
5533         klass = obj->vtable->klass;
5534
5535         /* Check for user defined reflection objects */
5536         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5537         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5538                 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
5539                 return 0;
5540         }
5541
5542         if (strcmp (klass->name, "MethodBuilder") == 0) {
5543                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5544                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5545
5546                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5547                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5548                 else {
5549                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5550                         if (!mono_error_ok (error))
5551                                 return 0;
5552                 }
5553                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5554         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5555                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5556                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5557
5558                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5559                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5560                 else {
5561                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5562                         if (!mono_error_ok (error))
5563                                 return 0;
5564                 }
5565                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5566         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5567                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5568                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5569                 if (tb->generic_params) {
5570                         token = mono_image_get_generic_field_token (assembly, fb, error);
5571                         return_val_if_nok (error, 0);
5572                 } else {
5573                         if (tb->module->dynamic_image == assembly) {
5574                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5575                         } else {
5576                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5577                         }
5578                 }
5579         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5580                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5581                 if (create_open_instance && tb->generic_params) {
5582                         MonoType *type;
5583                         init_type_builder_generics (obj);
5584                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5585                         return_val_if_nok (error, 0);
5586                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5587                         token = mono_metadata_token_from_dor (token);
5588                 } else if (tb->module->dynamic_image == assembly) {
5589                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5590                 } else {
5591                         MonoType *type;
5592                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5593                         return_val_if_nok (error, 0);
5594                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5595                 }
5596         } else if (strcmp (klass->name, "MonoType") == 0) {
5597                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5598                 return_val_if_nok (error, 0);
5599                 MonoClass *mc = mono_class_from_mono_type (type);
5600                 token = mono_metadata_token_from_dor (
5601                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5602         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5603                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5604                 return_val_if_nok (error, 0);
5605                 token = mono_metadata_token_from_dor (
5606                         mono_image_typedef_or_ref (assembly, type));
5607         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5608                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5609                 return_val_if_nok (error, 0);
5610                 token = mono_metadata_token_from_dor (
5611                         mono_image_typedef_or_ref (assembly, type));
5612         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5613                    strcmp (klass->name, "MonoMethod") == 0 ||
5614                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5615                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5616                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5617                 if (m->method->is_inflated) {
5618                         if (create_open_instance)
5619                                 token = mono_image_get_methodspec_token (assembly, m->method);
5620                         else
5621                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5622                 } else if ((m->method->klass->image == &assembly->image) &&
5623                          !m->method->klass->generic_class) {
5624                         static guint32 method_table_idx = 0xffffff;
5625                         if (m->method->klass->wastypebuilder) {
5626                                 /* we use the same token as the one that was assigned
5627                                  * to the Methodbuilder.
5628                                  * FIXME: do the equivalent for Fields.
5629                                  */
5630                                 token = m->method->token;
5631                         } else {
5632                                 /*
5633                                  * Each token should have a unique index, but the indexes are
5634                                  * assigned by managed code, so we don't know about them. An
5635                                  * easy solution is to count backwards...
5636                                  */
5637                                 method_table_idx --;
5638                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5639                         }
5640                 } else {
5641                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5642                 }
5643                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5644         } else if (strcmp (klass->name, "MonoField") == 0) {
5645                 MonoReflectionField *f = (MonoReflectionField *)obj;
5646                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5647                         static guint32 field_table_idx = 0xffffff;
5648                         field_table_idx --;
5649                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5650                 } else {
5651                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5652                 }
5653                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5654         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5655                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5656                 token = mono_image_get_array_token (assembly, m, error);
5657                 return_val_if_nok (error, 0);
5658         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5659                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5660                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5661                 return_val_if_nok (error, 0);
5662         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5663                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5664                 return_val_if_nok (error, 0);
5665                 token = mono_metadata_token_from_dor (
5666                         mono_image_typedef_or_ref (assembly, type));
5667         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5668                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5669                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5670                 return_val_if_nok (error, 0);
5671         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5672                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5673                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5674                 if (!mono_error_ok (error))
5675                         return 0;
5676         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5677                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5678                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5679                 if (!mono_error_ok (error))
5680                         return 0;
5681         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5682                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5683                 return_val_if_nok (error, 0);
5684                 token = mono_metadata_token_from_dor (
5685                                 mono_image_typedef_or_ref (assembly, type));
5686         } else {
5687                 g_error ("requested token for %s\n", klass->name);
5688         }
5689
5690         if (register_token)
5691                 mono_image_register_token (assembly, token, obj);
5692
5693         return token;
5694 }
5695
5696 /*
5697  * mono_image_register_token:
5698  *
5699  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5700  * the Module.ResolveXXXToken () methods to work.
5701  */
5702 void
5703 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5704 {
5705         MonoObject *prev;
5706
5707         dynamic_image_lock (assembly);
5708         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5709         if (prev) {
5710                 /* There could be multiple MethodInfo objects with the same token */
5711                 //g_assert (prev == obj);
5712         } else {
5713                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5714         }
5715         dynamic_image_unlock (assembly);
5716 }
5717
5718 static MonoDynamicImage*
5719 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5720 {
5721         static const guchar entrycode [16] = {0xff, 0x25, 0};
5722         MonoDynamicImage *image;
5723         int i;
5724
5725         const char *version;
5726
5727         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5728                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5729         else
5730                 version = mono_get_runtime_info ()->runtime_version;
5731
5732 #if HAVE_BOEHM_GC
5733         /* The MonoGHashTable's need GC tracking */
5734         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5735 #else
5736         image = g_new0 (MonoDynamicImage, 1);
5737 #endif
5738
5739         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5740         
5741         /*g_print ("created image %p\n", image);*/
5742         /* keep in sync with image.c */
5743         image->image.name = assembly_name;
5744         image->image.assembly_name = image->image.name; /* they may be different */
5745         image->image.module_name = module_name;
5746         image->image.version = g_strdup (version);
5747         image->image.md_version_major = 1;
5748         image->image.md_version_minor = 1;
5749         image->image.dynamic = TRUE;
5750
5751         image->image.references = g_new0 (MonoAssembly*, 1);
5752         image->image.references [0] = NULL;
5753
5754         mono_image_init (&image->image);
5755
5756         image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module token fixups table");
5757         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5758         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5759         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5760         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5761         image->handleref = g_hash_table_new (NULL, NULL);
5762         image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module reference-to-token table");
5763         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5764         image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module generic definitions table");
5765         image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module method specifications table");
5766         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5767         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5768         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5769         image->gen_params = g_ptr_array_new ();
5770         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5771
5772         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5773         string_heap_init (&image->sheap);
5774         mono_image_add_stream_data (&image->us, "", 1);
5775         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5776         /* import tables... */
5777         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5778         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5779         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5780         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5781         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5782         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5783         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5784         stream_data_align (&image->code);
5785
5786         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5787
5788         for (i=0; i < MONO_TABLE_NUM; ++i) {
5789                 image->tables [i].next_idx = 1;
5790                 image->tables [i].columns = table_sizes [i];
5791         }
5792
5793         image->image.assembly = (MonoAssembly*)assembly;
5794         image->run = assembly->run;
5795         image->save = assembly->save;
5796         image->pe_kind = 0x1; /* ILOnly */
5797         image->machine = 0x14c; /* I386 */
5798         
5799         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5800
5801         dynamic_images_lock ();
5802
5803         if (!dynamic_images)
5804                 dynamic_images = g_ptr_array_new ();
5805
5806         g_ptr_array_add (dynamic_images, image);
5807
5808         dynamic_images_unlock ();
5809
5810         return image;
5811 }
5812 #endif
5813
5814 static void
5815 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5816 {
5817         g_free (key);
5818 }
5819
5820 static void
5821 release_hashtable (MonoGHashTable **hash)
5822 {
5823         if (*hash) {
5824                 mono_g_hash_table_destroy (*hash);
5825                 *hash = NULL;
5826         }
5827 }
5828
5829 void
5830 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5831 {
5832         release_hashtable (&image->token_fixups);
5833         release_hashtable (&image->handleref_managed);
5834         release_hashtable (&image->tokens);
5835         release_hashtable (&image->remapped_tokens);
5836         release_hashtable (&image->generic_def_objects);
5837         release_hashtable (&image->methodspec);
5838 }
5839
5840 // Free dynamic image pass one: Free resources but not image itself
5841 void
5842 mono_dynamic_image_free (MonoDynamicImage *image)
5843 {
5844         MonoDynamicImage *di = image;
5845         GList *list;
5846         int i;
5847
5848         if (di->methodspec)
5849                 mono_g_hash_table_destroy (di->methodspec);
5850         if (di->typespec)
5851                 g_hash_table_destroy (di->typespec);
5852         if (di->typeref)
5853                 g_hash_table_destroy (di->typeref);
5854         if (di->handleref)
5855                 g_hash_table_destroy (di->handleref);
5856         if (di->handleref_managed)
5857                 mono_g_hash_table_destroy (di->handleref_managed);
5858         if (di->tokens)
5859                 mono_g_hash_table_destroy (di->tokens);
5860         if (di->remapped_tokens)
5861                 mono_g_hash_table_destroy (di->remapped_tokens);
5862         if (di->generic_def_objects)
5863                 mono_g_hash_table_destroy (di->generic_def_objects);
5864         if (di->blob_cache) {
5865                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5866                 g_hash_table_destroy (di->blob_cache);
5867         }
5868         if (di->standalonesig_cache)
5869                 g_hash_table_destroy (di->standalonesig_cache);
5870         for (list = di->array_methods; list; list = list->next) {
5871                 ArrayMethod *am = (ArrayMethod *)list->data;
5872                 g_free (am->sig);
5873                 g_free (am->name);
5874                 g_free (am);
5875         }
5876         g_list_free (di->array_methods);
5877         if (di->gen_params) {
5878                 for (i = 0; i < di->gen_params->len; i++) {
5879                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5880                         mono_gc_deregister_root ((char*) &entry->gparam);
5881                         g_free (entry);
5882                 }
5883                 g_ptr_array_free (di->gen_params, TRUE);
5884         }
5885         if (di->token_fixups)
5886                 mono_g_hash_table_destroy (di->token_fixups);
5887         if (di->method_to_table_idx)
5888                 g_hash_table_destroy (di->method_to_table_idx);
5889         if (di->field_to_table_idx)
5890                 g_hash_table_destroy (di->field_to_table_idx);
5891         if (di->method_aux_hash)
5892                 g_hash_table_destroy (di->method_aux_hash);
5893         if (di->vararg_aux_hash)
5894                 g_hash_table_destroy (di->vararg_aux_hash);
5895         g_free (di->strong_name);
5896         g_free (di->win32_res);
5897         if (di->public_key)
5898                 g_free (di->public_key);
5899
5900         /*g_print ("string heap destroy for image %p\n", di);*/
5901         mono_dynamic_stream_reset (&di->sheap);
5902         mono_dynamic_stream_reset (&di->code);
5903         mono_dynamic_stream_reset (&di->resources);
5904         mono_dynamic_stream_reset (&di->us);
5905         mono_dynamic_stream_reset (&di->blob);
5906         mono_dynamic_stream_reset (&di->tstream);
5907         mono_dynamic_stream_reset (&di->guid);
5908         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5909                 g_free (di->tables [i].values);
5910         }
5911
5912         dynamic_images_lock ();
5913
5914         if (dynamic_images)
5915                 g_ptr_array_remove (dynamic_images, di);
5916
5917         dynamic_images_unlock ();
5918 }
5919
5920 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5921 void
5922 mono_dynamic_image_free_image (MonoDynamicImage *image)
5923 {
5924         /* See create_dynamic_mono_image () */
5925 #if HAVE_BOEHM_GC
5926         /* Allocated using GC_MALLOC */
5927 #else
5928         g_free (image);
5929 #endif
5930 }
5931
5932 #ifndef DISABLE_REFLECTION_EMIT
5933
5934 /*
5935  * mono_image_basic_init:
5936  * @assembly: an assembly builder object
5937  *
5938  * Create the MonoImage that represents the assembly builder and setup some
5939  * of the helper hash table and the basic metadata streams.
5940  */
5941 void
5942 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5943 {
5944         MonoDynamicAssembly *assembly;
5945         MonoDynamicImage *image;
5946         MonoDomain *domain = mono_object_domain (assemblyb);
5947         
5948         if (assemblyb->dynamic_assembly)
5949                 return;
5950
5951 #if HAVE_BOEHM_GC
5952         /* assembly->assembly.image might be GC allocated */
5953         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5954 #else
5955         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5956 #endif
5957
5958         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5959         
5960         assembly->assembly.ref_count = 1;
5961         assembly->assembly.dynamic = TRUE;
5962         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5963         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5964         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5965         if (assemblyb->culture)
5966                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5967         else
5968                 assembly->assembly.aname.culture = g_strdup ("");
5969
5970         if (assemblyb->version) {
5971                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5972                         char **version = g_strsplit (vstr, ".", 4);
5973                         char **parts = version;
5974                         assembly->assembly.aname.major = atoi (*parts++);
5975                         assembly->assembly.aname.minor = atoi (*parts++);
5976                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5977                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5978
5979                         g_strfreev (version);
5980                         g_free (vstr);
5981         } else {
5982                         assembly->assembly.aname.major = 0;
5983                         assembly->assembly.aname.minor = 0;
5984                         assembly->assembly.aname.build = 0;
5985                         assembly->assembly.aname.revision = 0;
5986         }
5987
5988         assembly->run = assemblyb->access != 2;
5989         assembly->save = assemblyb->access != 1;
5990         assembly->domain = domain;
5991
5992         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5993         image->initial_image = TRUE;
5994         assembly->assembly.aname.name = image->image.name;
5995         assembly->assembly.image = &image->image;
5996         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5997                 /* -1 to correct for the trailing NULL byte */
5998                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5999                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
6000                 }
6001                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
6002         }
6003
6004         mono_domain_assemblies_lock (domain);
6005         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6006         mono_domain_assemblies_unlock (domain);
6007
6008         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6009         
6010         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6011         
6012         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6013 }
6014
6015 #endif /* !DISABLE_REFLECTION_EMIT */
6016
6017 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6018
6019 static int
6020 calc_section_size (MonoDynamicImage *assembly)
6021 {
6022         int nsections = 0;
6023
6024         /* alignment constraints */
6025         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6026         g_assert ((assembly->code.index % 4) == 0);
6027         assembly->meta_size += 3;
6028         assembly->meta_size &= ~3;
6029         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6030         g_assert ((assembly->resources.index % 4) == 0);
6031
6032         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6033         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6034         nsections++;
6035
6036         if (assembly->win32_res) {
6037                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6038
6039                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6040                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6041                 nsections++;
6042         }
6043
6044         assembly->sections [MONO_SECTION_RELOC].size = 12;
6045         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6046         nsections++;
6047
6048         return nsections;
6049 }
6050
6051 typedef struct {
6052         guint32 id;
6053         guint32 offset;
6054         GSList *children;
6055         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6056 } ResTreeNode;
6057
6058 static int
6059 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6060 {
6061         ResTreeNode *t1 = (ResTreeNode*)a;
6062         ResTreeNode *t2 = (ResTreeNode*)b;
6063
6064         return t1->id - t2->id;
6065 }
6066
6067 /*
6068  * resource_tree_create:
6069  *
6070  *  Organize the resources into a resource tree.
6071  */
6072 static ResTreeNode *
6073 resource_tree_create (MonoArray *win32_resources)
6074 {
6075         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6076         GSList *l;
6077         int i;
6078
6079         tree = g_new0 (ResTreeNode, 1);
6080         
6081         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6082                 MonoReflectionWin32Resource *win32_res =
6083                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6084
6085                 /* Create node */
6086
6087                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6088                 lang_node = g_new0 (ResTreeNode, 1);
6089                 lang_node->id = win32_res->lang_id;
6090                 lang_node->win32_res = win32_res;
6091
6092                 /* Create type node if neccesary */
6093                 type_node = NULL;
6094                 for (l = tree->children; l; l = l->next)
6095                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6096                                 type_node = (ResTreeNode*)l->data;
6097                                 break;
6098                         }
6099
6100                 if (!type_node) {
6101                         type_node = g_new0 (ResTreeNode, 1);
6102                         type_node->id = win32_res->res_type;
6103
6104                         /* 
6105                          * The resource types have to be sorted otherwise
6106                          * Windows Explorer can't display the version information.
6107                          */
6108                         tree->children = g_slist_insert_sorted (tree->children, 
6109                                 type_node, resource_tree_compare_by_id);
6110                 }
6111
6112                 /* Create res node if neccesary */
6113                 res_node = NULL;
6114                 for (l = type_node->children; l; l = l->next)
6115                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6116                                 res_node = (ResTreeNode*)l->data;
6117                                 break;
6118                         }
6119
6120                 if (!res_node) {
6121                         res_node = g_new0 (ResTreeNode, 1);
6122                         res_node->id = win32_res->res_id;
6123                         type_node->children = g_slist_append (type_node->children, res_node);
6124                 }
6125
6126                 res_node->children = g_slist_append (res_node->children, lang_node);
6127         }
6128
6129         return tree;
6130 }
6131
6132 /*
6133  * resource_tree_encode:
6134  * 
6135  *   Encode the resource tree into the format used in the PE file.
6136  */
6137 static void
6138 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6139 {
6140         char *entries;
6141         MonoPEResourceDir dir;
6142         MonoPEResourceDirEntry dir_entry;
6143         MonoPEResourceDataEntry data_entry;
6144         GSList *l;
6145         guint32 res_id_entries;
6146
6147         /*
6148          * For the format of the resource directory, see the article
6149          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6150          * Matt Pietrek
6151          */
6152
6153         memset (&dir, 0, sizeof (dir));
6154         memset (&dir_entry, 0, sizeof (dir_entry));
6155         memset (&data_entry, 0, sizeof (data_entry));
6156
6157         g_assert (sizeof (dir) == 16);
6158         g_assert (sizeof (dir_entry) == 8);
6159         g_assert (sizeof (data_entry) == 16);
6160
6161         node->offset = p - begin;
6162
6163         /* IMAGE_RESOURCE_DIRECTORY */
6164         res_id_entries = g_slist_length (node->children);
6165         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6166
6167         memcpy (p, &dir, sizeof (dir));
6168         p += sizeof (dir);
6169
6170         /* Reserve space for entries */
6171         entries = p;
6172         p += sizeof (dir_entry) * res_id_entries;
6173
6174         /* Write children */
6175         for (l = node->children; l; l = l->next) {
6176                 ResTreeNode *child = (ResTreeNode*)l->data;
6177
6178                 if (child->win32_res) {
6179                         guint32 size;
6180
6181                         child->offset = p - begin;
6182
6183                         /* IMAGE_RESOURCE_DATA_ENTRY */
6184                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6185                         size = mono_array_length (child->win32_res->res_data);
6186                         data_entry.rde_size = GUINT32_TO_LE (size);
6187
6188                         memcpy (p, &data_entry, sizeof (data_entry));
6189                         p += sizeof (data_entry);
6190
6191                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6192                         p += size;
6193                 } else {
6194                         resource_tree_encode (child, begin, p, &p);
6195                 }
6196         }
6197
6198         /* IMAGE_RESOURCE_ENTRY */
6199         for (l = node->children; l; l = l->next) {
6200                 ResTreeNode *child = (ResTreeNode*)l->data;
6201
6202                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6203                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6204
6205                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6206                 entries += sizeof (dir_entry);
6207         }
6208
6209         *endbuf = p;
6210 }
6211
6212 static void
6213 resource_tree_free (ResTreeNode * node)
6214 {
6215         GSList * list;
6216         for (list = node->children; list; list = list->next)
6217                 resource_tree_free ((ResTreeNode*)list->data);
6218         g_slist_free(node->children);
6219         g_free (node);
6220 }
6221
6222 static void
6223 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6224 {
6225         char *buf;
6226         char *p;
6227         guint32 size, i;
6228         MonoReflectionWin32Resource *win32_res;
6229         ResTreeNode *tree;
6230
6231         if (!assemblyb->win32_resources)
6232                 return;
6233
6234         /*
6235          * Resources are stored in a three level tree inside the PE file.
6236          * - level one contains a node for each type of resource
6237          * - level two contains a node for each resource
6238          * - level three contains a node for each instance of a resource for a
6239          *   specific language.
6240          */
6241
6242         tree = resource_tree_create (assemblyb->win32_resources);
6243
6244         /* Estimate the size of the encoded tree */
6245         size = 0;
6246         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6247                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6248                 size += mono_array_length (win32_res->res_data);
6249         }
6250         /* Directory structure */
6251         size += mono_array_length (assemblyb->win32_resources) * 256;
6252         p = buf = (char *)g_malloc (size);
6253
6254         resource_tree_encode (tree, p, p, &p);
6255
6256         g_assert (p - buf <= size);
6257
6258         assembly->win32_res = (char *)g_malloc (p - buf);
6259         assembly->win32_res_size = p - buf;
6260         memcpy (assembly->win32_res, buf, p - buf);
6261
6262         g_free (buf);
6263         resource_tree_free (tree);
6264 }
6265
6266 static void
6267 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6268 {
6269         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6270         int i;
6271
6272         p += sizeof (MonoPEResourceDir);
6273         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6274                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6275                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6276                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6277                         fixup_resource_directory (res_section, child, rva);
6278                 } else {
6279                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6280                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6281                 }
6282
6283                 p += sizeof (MonoPEResourceDirEntry);
6284         }
6285 }
6286
6287 static void
6288 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6289 {
6290         guint32 dummy;
6291         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6292                 g_error ("WriteFile returned %d\n", GetLastError ());
6293 }
6294
6295 /*
6296  * mono_image_create_pefile:
6297  * @mb: a module builder object
6298  * 
6299  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6300  * assembly->pefile where it can be easily retrieved later in chunks.
6301  */
6302 gboolean
6303 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6304 {
6305         MonoMSDOSHeader *msdos;
6306         MonoDotNetHeader *header;
6307         MonoSectionTable *section;
6308         MonoCLIHeader *cli_header;
6309         guint32 size, image_size, virtual_base, text_offset;
6310         guint32 header_start, section_start, file_offset, virtual_offset;
6311         MonoDynamicImage *assembly;
6312         MonoReflectionAssemblyBuilder *assemblyb;
6313         MonoDynamicStream pefile_stream = {0};
6314         MonoDynamicStream *pefile = &pefile_stream;
6315         int i, nsections;
6316         guint32 *rva, value;
6317         guchar *p;
6318         static const unsigned char msheader[] = {
6319                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6320                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6321                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6322                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6323                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6324                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6325                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6326                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6327         };
6328
6329         mono_error_init (error);
6330
6331         assemblyb = mb->assemblyb;
6332
6333         mono_image_basic_init (assemblyb);
6334         assembly = mb->dynamic_image;
6335
6336         assembly->pe_kind = assemblyb->pe_kind;
6337         assembly->machine = assemblyb->machine;
6338         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6339         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6340         
6341         if (!mono_image_build_metadata (mb, error))
6342                 return FALSE;
6343         
6344
6345         if (mb->is_main && assemblyb->resources) {
6346                 int len = mono_array_length (assemblyb->resources);
6347                 for (i = 0; i < len; ++i)
6348                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6349         }
6350
6351         if (mb->resources) {
6352                 int len = mono_array_length (mb->resources);
6353                 for (i = 0; i < len; ++i)
6354                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6355         }
6356
6357         if (!build_compressed_metadata (assembly, error))
6358                 return FALSE;
6359
6360         if (mb->is_main)
6361                 assembly_add_win32_resources (assembly, assemblyb);
6362
6363         nsections = calc_section_size (assembly);
6364         
6365         /* The DOS header and stub */
6366         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6367         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6368
6369         /* the dotnet header */
6370         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6371
6372         /* the section tables */
6373         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6374
6375         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6376         virtual_offset = VIRT_ALIGN;
6377         image_size = 0;
6378
6379         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6380                 if (!assembly->sections [i].size)
6381                         continue;
6382                 /* align offsets */
6383                 file_offset += FILE_ALIGN - 1;
6384                 file_offset &= ~(FILE_ALIGN - 1);
6385                 virtual_offset += VIRT_ALIGN - 1;
6386                 virtual_offset &= ~(VIRT_ALIGN - 1);
6387
6388                 assembly->sections [i].offset = file_offset;
6389                 assembly->sections [i].rva = virtual_offset;
6390
6391                 file_offset += assembly->sections [i].size;
6392                 virtual_offset += assembly->sections [i].size;
6393                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6394         }
6395
6396         file_offset += FILE_ALIGN - 1;
6397         file_offset &= ~(FILE_ALIGN - 1);
6398
6399         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6400
6401         /* back-patch info */
6402         msdos = (MonoMSDOSHeader*)pefile->data;
6403         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6404
6405         header = (MonoDotNetHeader*)(pefile->data + header_start);
6406         header->pesig [0] = 'P';
6407         header->pesig [1] = 'E';
6408         
6409         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6410         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6411         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6412         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6413         if (assemblyb->pekind == 1) {
6414                 /* it's a dll */
6415                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6416         } else {
6417                 /* it's an exe */
6418                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6419         }
6420
6421         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6422
6423         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6424         header->pe.pe_major = 6;
6425         header->pe.pe_minor = 0;
6426         size = assembly->sections [MONO_SECTION_TEXT].size;
6427         size += FILE_ALIGN - 1;
6428         size &= ~(FILE_ALIGN - 1);
6429         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6430         size = assembly->sections [MONO_SECTION_RSRC].size;
6431         size += FILE_ALIGN - 1;
6432         size &= ~(FILE_ALIGN - 1);
6433         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6434         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6435         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6436         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6437         /* pe_rva_entry_point always at the beginning of the text section */
6438         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6439
6440         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6441         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6442         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6443         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6444         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6445         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6446         size = section_start;
6447         size += FILE_ALIGN - 1;
6448         size &= ~(FILE_ALIGN - 1);
6449         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6450         size = image_size;
6451         size += VIRT_ALIGN - 1;
6452         size &= ~(VIRT_ALIGN - 1);
6453         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6454
6455         /*
6456         // Translate the PEFileKind value to the value expected by the Windows loader
6457         */
6458         {
6459                 short kind;
6460
6461                 /*
6462                 // PEFileKinds.Dll == 1
6463                 // PEFileKinds.ConsoleApplication == 2
6464                 // PEFileKinds.WindowApplication == 3
6465                 //
6466                 // need to get:
6467                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6468                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6469                 */
6470                 if (assemblyb->pekind == 3)
6471                         kind = 2;
6472                 else
6473                         kind = 3;
6474                 
6475                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6476         }    
6477         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6478         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6479         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6480         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6481         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6482         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6483
6484         /* fill data directory entries */
6485
6486         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6487         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6488
6489         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6490         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6491
6492         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6493         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6494         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6495         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6496         /* patch entrypoint name */
6497         if (assemblyb->pekind == 1)
6498                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6499         else
6500                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6501         /* patch imported function RVA name */
6502         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6503         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6504
6505         /* the import table */
6506         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6507         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6508         /* patch imported dll RVA name and other entries in the dir */
6509         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6510         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6511         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6512         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6513         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6514         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6515
6516         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6517         value = (assembly->text_rva + assembly->imp_names_offset);
6518         *p++ = (value) & 0xff;
6519         *p++ = (value >> 8) & (0xff);
6520         *p++ = (value >> 16) & (0xff);
6521         *p++ = (value >> 24) & (0xff);
6522
6523         /* the CLI header info */
6524         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6525         cli_header->ch_size = GUINT32_FROM_LE (72);
6526         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6527         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6528         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6529         if (assemblyb->entry_point) {
6530                 guint32 table_idx = 0;
6531                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6532                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6533                         table_idx = methodb->table_idx;
6534                 } else {
6535                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6536                 }
6537                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6538         } else {
6539                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6540         }
6541         /* The embedded managed resources */
6542         text_offset = assembly->text_rva + assembly->code.index;
6543         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6544         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6545         text_offset += assembly->resources.index;
6546         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6547         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6548         text_offset += assembly->meta_size;
6549         if (assembly->strong_name_size) {
6550                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6551                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6552                 text_offset += assembly->strong_name_size;
6553         }
6554
6555         /* write the section tables and section content */
6556         section = (MonoSectionTable*)(pefile->data + section_start);
6557         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558                 static const char section_names [][7] = {
6559                         ".text", ".rsrc", ".reloc"
6560                 };
6561                 if (!assembly->sections [i].size)
6562                         continue;
6563                 strcpy (section->st_name, section_names [i]);
6564                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6565                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6566                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6567                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6568                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6569                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6570                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6571                 section ++;
6572         }
6573         
6574         checked_write_file (file, pefile->data, pefile->index);
6575         
6576         mono_dynamic_stream_reset (pefile);
6577         
6578         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6579                 if (!assembly->sections [i].size)
6580                         continue;
6581                 
6582                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6583                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6584                 
6585                 switch (i) {
6586                 case MONO_SECTION_TEXT:
6587                         /* patch entry point */
6588                         p = (guchar*)(assembly->code.data + 2);
6589                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6590                         *p++ = (value) & 0xff;
6591                         *p++ = (value >> 8) & 0xff;
6592                         *p++ = (value >> 16) & 0xff;
6593                         *p++ = (value >> 24) & 0xff;
6594                 
6595                         checked_write_file (file, assembly->code.data, assembly->code.index);
6596                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6597                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6598                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6599                                 
6600
6601                         g_free (assembly->image.raw_metadata);
6602                         break;
6603                 case MONO_SECTION_RELOC: {
6604                         struct {
6605                                 guint32 page_rva;
6606                                 guint32 block_size;
6607                                 guint16 type_and_offset;
6608                                 guint16 term;
6609                         } reloc;
6610                         
6611                         g_assert (sizeof (reloc) == 12);
6612                         
6613                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6614                         reloc.block_size = GUINT32_FROM_LE (12);
6615                         
6616                         /* 
6617                          * the entrypoint is always at the start of the text section 
6618                          * 3 is IMAGE_REL_BASED_HIGHLOW
6619                          * 2 is patch_size_rva - text_rva
6620                          */
6621                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6622                         reloc.term = 0;
6623                         
6624                         checked_write_file (file, &reloc, sizeof (reloc));
6625                         
6626                         break;
6627                 }
6628                 case MONO_SECTION_RSRC:
6629                         if (assembly->win32_res) {
6630
6631                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6632                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6633                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6634                         }
6635                         break;
6636                 default:
6637                         g_assert_not_reached ();
6638                 }
6639         }
6640         
6641         /* check that the file is properly padded */
6642         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6643                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6644         if (! SetEndOfFile (file))
6645                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6646         
6647         mono_dynamic_stream_reset (&assembly->code);
6648         mono_dynamic_stream_reset (&assembly->us);
6649         mono_dynamic_stream_reset (&assembly->blob);
6650         mono_dynamic_stream_reset (&assembly->guid);
6651         mono_dynamic_stream_reset (&assembly->sheap);
6652
6653         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6654         g_hash_table_destroy (assembly->blob_cache);
6655         assembly->blob_cache = NULL;
6656
6657         return TRUE;
6658 }
6659
6660 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6661
6662 gboolean
6663 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6664 {
6665         g_assert_not_reached ();
6666 }
6667
6668 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6669
6670 #ifndef DISABLE_REFLECTION_EMIT
6671
6672 MonoReflectionModule *
6673 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
6674 {
6675         char *name;
6676         MonoImage *image;
6677         MonoImageOpenStatus status;
6678         MonoDynamicAssembly *assembly;
6679         guint32 module_count;
6680         MonoImage **new_modules;
6681         gboolean *new_modules_loaded;
6682         
6683         mono_error_init (error);
6684         
6685         name = mono_string_to_utf8 (fileName);
6686
6687         image = mono_image_open (name, &status);
6688         if (!image) {
6689                 if (status == MONO_IMAGE_ERROR_ERRNO)
6690                         mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6691                 else
6692                         mono_error_set_bad_image_name (error, name, NULL);
6693                 g_free (name);
6694                 return NULL;
6695         }
6696
6697         g_free (name);
6698
6699         assembly = ab->dynamic_assembly;
6700         image->assembly = (MonoAssembly*)assembly;
6701
6702         module_count = image->assembly->image->module_count;
6703         new_modules = g_new0 (MonoImage *, module_count + 1);
6704         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6705
6706         if (image->assembly->image->modules)
6707                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6708         if (image->assembly->image->modules_loaded)
6709                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6710         new_modules [module_count] = image;
6711         new_modules_loaded [module_count] = TRUE;
6712         mono_image_addref (image);
6713
6714         g_free (image->assembly->image->modules);
6715         image->assembly->image->modules = new_modules;
6716         image->assembly->image->modules_loaded = new_modules_loaded;
6717         image->assembly->image->module_count ++;
6718
6719         mono_assembly_load_references (image, &status);
6720         if (status) {
6721                 mono_image_close (image);
6722                 mono_error_set_exception_instance (error, mono_get_exception_file_not_found (fileName));
6723                 return NULL;
6724         }
6725
6726         return mono_module_get_object_checked (mono_domain_get (), image, error);
6727 }
6728
6729 #endif /* DISABLE_REFLECTION_EMIT */
6730
6731 /*
6732  * We need to return always the same object for MethodInfo, FieldInfo etc..
6733  * but we need to consider the reflected type.
6734  * type uses a different hash, since it uses custom hash/equal functions.
6735  */
6736
6737 typedef struct {
6738         gpointer item;
6739         MonoClass *refclass;
6740 } ReflectedEntry;
6741
6742 static gboolean
6743 reflected_equal (gconstpointer a, gconstpointer b) {
6744         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6745         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6746
6747         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6748 }
6749
6750 static guint
6751 reflected_hash (gconstpointer a) {
6752         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6753         return mono_aligned_addr_hash (ea->item);
6754 }
6755
6756 #define CHECK_OBJECT(t,p,k)     \
6757         do {    \
6758                 t _obj; \
6759                 ReflectedEntry e;       \
6760                 e.item = (p);   \
6761                 e.refclass = (k);       \
6762                 mono_domain_lock (domain);      \
6763                 if (!domain->refobject_hash)    \
6764                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6765                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6766                         mono_domain_unlock (domain);    \
6767                         return _obj;    \
6768                 }       \
6769         mono_domain_unlock (domain); \
6770         } while (0)
6771
6772 #ifdef HAVE_BOEHM_GC
6773 /* ReflectedEntry doesn't need to be GC tracked */
6774 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6775 #define FREE_REFENTRY(entry) g_free ((entry))
6776 #define REFENTRY_REQUIRES_CLEANUP
6777 #else
6778 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6779 /* FIXME: */
6780 #define FREE_REFENTRY(entry)
6781 #endif
6782
6783 #define CACHE_OBJECT(t,p,o,k)   \
6784         do {    \
6785                 t _obj; \
6786         ReflectedEntry pe; \
6787         pe.item = (p); \
6788         pe.refclass = (k); \
6789         mono_domain_lock (domain); \
6790                 if (!domain->refobject_hash)    \
6791                         domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection objects table");  \
6792         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6793         if (!_obj) { \
6794                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6795                     e->item = (p);      \
6796                     e->refclass = (k);  \
6797                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6798             _obj = o; \
6799         } \
6800                 mono_domain_unlock (domain);    \
6801         return _obj; \
6802         } while (0)
6803
6804 static void
6805 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6806 {
6807         mono_domain_lock (domain);
6808         if (domain->refobject_hash) {
6809         ReflectedEntry pe;
6810                 gpointer orig_pe, orig_value;
6811
6812                 pe.item = o;
6813                 pe.refclass = klass;
6814                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6815                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6816                         FREE_REFENTRY (orig_pe);
6817                 }
6818         }
6819         mono_domain_unlock (domain);
6820 }
6821
6822 #ifdef REFENTRY_REQUIRES_CLEANUP
6823 static void
6824 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6825 {
6826         FREE_REFENTRY (key);
6827 }
6828 #endif
6829
6830 void
6831 mono_reflection_cleanup_domain (MonoDomain *domain)
6832 {
6833         if (domain->refobject_hash) {
6834 /*let's avoid scanning the whole hashtable if not needed*/
6835 #ifdef REFENTRY_REQUIRES_CLEANUP
6836                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6837 #endif
6838                 mono_g_hash_table_destroy (domain->refobject_hash);
6839                 domain->refobject_hash = NULL;
6840         }
6841 }
6842
6843 #ifndef DISABLE_REFLECTION_EMIT
6844 static gpointer
6845 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6846 {
6847         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6848 }
6849
6850 static gpointer
6851 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6852 {
6853         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6854 }
6855
6856 void
6857 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6858 {
6859         MonoDynamicImage *image = moduleb->dynamic_image;
6860         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6861         if (!image) {
6862                 MonoError error;
6863                 int module_count;
6864                 MonoImage **new_modules;
6865                 MonoImage *ass;
6866                 char *name, *fqname;
6867                 /*
6868                  * FIXME: we already created an image in mono_image_basic_init (), but
6869                  * we don't know which module it belongs to, since that is only 
6870                  * determined at assembly save time.
6871                  */
6872                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6873                 name = mono_string_to_utf8 (ab->name);
6874                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6875                 if (!mono_error_ok (&error)) {
6876                         g_free (name);
6877                         mono_error_raise_exception (&error);
6878                 }
6879                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6880
6881                 moduleb->module.image = &image->image;
6882                 moduleb->dynamic_image = image;
6883                 register_module (mono_object_domain (moduleb), moduleb, image);
6884
6885                 /* register the module with the assembly */
6886                 ass = ab->dynamic_assembly->assembly.image;
6887                 module_count = ass->module_count;
6888                 new_modules = g_new0 (MonoImage *, module_count + 1);
6889
6890                 if (ass->modules)
6891                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6892                 new_modules [module_count] = &image->image;
6893                 mono_image_addref (&image->image);
6894
6895                 g_free (ass->modules);
6896                 ass->modules = new_modules;
6897                 ass->module_count ++;
6898         }
6899 }
6900
6901 void
6902 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6903 {
6904         MonoDynamicImage *image = moduleb->dynamic_image;
6905
6906         g_assert (type->type);
6907         image->wrappers_type = mono_class_from_mono_type (type->type);
6908 }
6909
6910 #endif
6911
6912 /*
6913  * mono_assembly_get_object:
6914  * @domain: an app domain
6915  * @assembly: an assembly
6916  *
6917  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6918  */
6919 MonoReflectionAssembly*
6920 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6921 {
6922         MonoError error;
6923         MonoReflectionAssembly *result;
6924         result = mono_assembly_get_object_checked (domain, assembly, &error);
6925         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6926         return result;
6927 }
6928 /*
6929  * mono_assembly_get_object_checked:
6930  * @domain: an app domain
6931  * @assembly: an assembly
6932  *
6933  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6934  */
6935 MonoReflectionAssembly*
6936 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6937 {
6938         MonoReflectionAssembly *res;
6939         
6940         mono_error_init (error);
6941
6942         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6943         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6944         if (!res)
6945                 return NULL;
6946         res->assembly = assembly;
6947
6948         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6949 }
6950
6951
6952
6953 MonoReflectionModule*   
6954 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6955 {
6956         MonoError error;
6957         MonoReflectionModule *result;
6958         result = mono_module_get_object_checked (domain, image, &error);
6959         mono_error_raise_exception (&error);
6960         return result;
6961 }
6962
6963 MonoReflectionModule*
6964 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6965 {
6966         MonoReflectionModule *res;
6967         char* basename;
6968         
6969         mono_error_init (error);
6970         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6971         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6972         if (!res)
6973                 return NULL;
6974
6975         res->image = image;
6976         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6977         if (!assm_obj)
6978                 return NULL;
6979         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6980
6981         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6982         basename = g_path_get_basename (image->name);
6983         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6984         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6985         
6986         g_free (basename);
6987
6988         if (image->assembly->image == image) {
6989                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6990         } else {
6991                 int i;
6992                 res->token = 0;
6993                 if (image->assembly->image->modules) {
6994                         for (i = 0; i < image->assembly->image->module_count; i++) {
6995                                 if (image->assembly->image->modules [i] == image)
6996                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6997                         }
6998                         g_assert (res->token);
6999                 }
7000         }
7001
7002         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7003 }
7004
7005 MonoReflectionModule*
7006 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7007 {
7008         MonoError error;
7009         MonoReflectionModule *result;
7010         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7011         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7012         return result;
7013 }
7014
7015 MonoReflectionModule*
7016 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7017 {
7018         MonoReflectionModule *res;
7019         MonoTableInfo *table;
7020         guint32 cols [MONO_FILE_SIZE];
7021         const char *name;
7022         guint32 i, name_idx;
7023         const char *val;
7024         
7025         mono_error_init (error);
7026
7027         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7028         if (!res)
7029                 return NULL;
7030
7031         table = &image->tables [MONO_TABLE_FILE];
7032         g_assert (table_index < table->rows);
7033         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7034
7035         res->image = NULL;
7036         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7037         if (!assm_obj)
7038                 return NULL;
7039         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7040         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7041
7042         /* Check whenever the row has a corresponding row in the moduleref table */
7043         table = &image->tables [MONO_TABLE_MODULEREF];
7044         for (i = 0; i < table->rows; ++i) {
7045                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7046                 val = mono_metadata_string_heap (image, name_idx);
7047                 if (strcmp (val, name) == 0)
7048                         res->image = image->modules [i];
7049         }
7050
7051         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7052         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7053         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7054         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7055         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7056
7057         return res;
7058 }
7059
7060 static gboolean
7061 verify_safe_for_managed_space (MonoType *type)
7062 {
7063         switch (type->type) {
7064 #ifdef DEBUG_HARDER
7065         case MONO_TYPE_ARRAY:
7066                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7067         case MONO_TYPE_PTR:
7068                 return verify_safe_for_managed_space (type->data.type);
7069         case MONO_TYPE_SZARRAY:
7070                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7071         case MONO_TYPE_GENERICINST: {
7072                 MonoGenericInst *inst = type->data.generic_class->inst;
7073                 int i;
7074                 if (!inst->is_open)
7075                         break;
7076                 for (i = 0; i < inst->type_argc; ++i)
7077                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7078                                 return FALSE;
7079                 return TRUE;
7080         }
7081 #endif
7082         case MONO_TYPE_VAR:
7083         case MONO_TYPE_MVAR:
7084                 return TRUE;
7085         default:
7086                 return TRUE;
7087         }
7088 }
7089
7090 static MonoType*
7091 mono_type_normalize (MonoType *type)
7092 {
7093         int i;
7094         MonoGenericClass *gclass;
7095         MonoGenericInst *ginst;
7096         MonoClass *gtd;
7097         MonoGenericContainer *gcontainer;
7098         MonoType **argv = NULL;
7099         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7100
7101         if (type->type != MONO_TYPE_GENERICINST)
7102                 return type;
7103
7104         gclass = type->data.generic_class;
7105         ginst = gclass->context.class_inst;
7106         if (!ginst->is_open)
7107                 return type;
7108
7109         gtd = gclass->container_class;
7110         gcontainer = gtd->generic_container;
7111         argv = g_newa (MonoType*, ginst->type_argc);
7112
7113         for (i = 0; i < ginst->type_argc; ++i) {
7114                 MonoType *t = ginst->type_argv [i], *norm;
7115                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7116                         is_denorm_gtd = FALSE;
7117                 norm = mono_type_normalize (t);
7118                 argv [i] = norm;
7119                 if (norm != t)
7120                         requires_rebind = TRUE;
7121         }
7122
7123         if (is_denorm_gtd)
7124                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7125
7126         if (requires_rebind) {
7127                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7128                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7129         }
7130
7131         return type;
7132 }
7133 /*
7134  * mono_type_get_object:
7135  * @domain: an app domain
7136  * @type: a type
7137  *
7138  * Return an System.MonoType object representing the type @type.
7139  */
7140 MonoReflectionType*
7141 mono_type_get_object (MonoDomain *domain, MonoType *type)
7142 {
7143         MonoError error;
7144         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7145         mono_error_raise_exception (&error);
7146
7147         return ret;
7148 }
7149
7150 MonoReflectionType*
7151 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7152 {
7153         MonoType *norm_type;
7154         MonoReflectionType *res;
7155         MonoClass *klass;
7156
7157         mono_error_init (error);
7158
7159         klass = mono_class_from_mono_type (type);
7160
7161         /*we must avoid using @type as it might have come
7162          * from a mono_metadata_type_dup and the caller
7163          * expects that is can be freed.
7164          * Using the right type from 
7165          */
7166         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7167
7168         /* void is very common */
7169         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7170                 return (MonoReflectionType*)domain->typeof_void;
7171
7172         /*
7173          * If the vtable of the given class was already created, we can use
7174          * the MonoType from there and avoid all locking and hash table lookups.
7175          * 
7176          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7177          * that the resulting object is different.   
7178          */
7179         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7180                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7181                 if (vtable && vtable->type)
7182                         return (MonoReflectionType *)vtable->type;
7183         }
7184
7185         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7186         mono_domain_lock (domain);
7187         if (!domain->type_hash)
7188                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7189                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7190         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7191                 mono_domain_unlock (domain);
7192                 mono_loader_unlock ();
7193                 return res;
7194         }
7195
7196         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7197          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7198          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7199          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7200          * artifact of how generics are encoded and should be transparent to managed code so we
7201          * need to weed out this diference when retrieving managed System.Type objects.
7202          */
7203         norm_type = mono_type_normalize (type);
7204         if (norm_type != type) {
7205                 res = mono_type_get_object_checked (domain, norm_type, error);
7206                 if (!mono_error_ok (error))
7207                         return NULL;
7208                 mono_g_hash_table_insert (domain->type_hash, type, res);
7209                 mono_domain_unlock (domain);
7210                 mono_loader_unlock ();
7211                 return res;
7212         }
7213
7214         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7215         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7216                 g_assert (0);
7217
7218         if (!verify_safe_for_managed_space (type)) {
7219                 mono_domain_unlock (domain);
7220                 mono_loader_unlock ();
7221                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7222                 return NULL;
7223         }
7224
7225         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7226                 gboolean is_type_done = TRUE;
7227                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7228                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7229                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7230                 */
7231                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7232                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7233
7234                         if (gparam->owner && gparam->owner->is_method) {
7235                                 MonoMethod *method = gparam->owner->owner.method;
7236                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7237                                         is_type_done = FALSE;
7238                         } else if (gparam->owner && !gparam->owner->is_method) {
7239                                 MonoClass *klass = gparam->owner->owner.klass;
7240                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7241                                         is_type_done = FALSE;
7242                         }
7243                 } 
7244
7245                 /* g_assert_not_reached (); */
7246                 /* should this be considered an error condition? */
7247                 if (is_type_done && !type->byref) {
7248                         mono_domain_unlock (domain);
7249                         mono_loader_unlock ();
7250                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7251                 }
7252         }
7253         /* This is stored in vtables/JITted code so it has to be pinned */
7254         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7255         if (!mono_error_ok (error))
7256                 return NULL;
7257
7258         res->type = type;
7259         mono_g_hash_table_insert (domain->type_hash, type, res);
7260
7261         if (type->type == MONO_TYPE_VOID)
7262                 domain->typeof_void = (MonoObject*)res;
7263
7264         mono_domain_unlock (domain);
7265         mono_loader_unlock ();
7266         return res;
7267 }
7268
7269 /*
7270  * mono_method_get_object:
7271  * @domain: an app domain
7272  * @method: a method
7273  * @refclass: the reflected type (can be NULL)
7274  *
7275  * Return an System.Reflection.MonoMethod object representing the method @method.
7276  */
7277 MonoReflectionMethod*
7278 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7279 {
7280         MonoError error;
7281         MonoReflectionMethod *ret = NULL;
7282         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7283         mono_error_raise_exception (&error);
7284         return ret;
7285 }
7286
7287 /*
7288  * mono_method_get_object_checked:
7289  * @domain: an app domain
7290  * @method: a method
7291  * @refclass: the reflected type (can be NULL)
7292  * @error: set on error.
7293  *
7294  * Return an System.Reflection.MonoMethod object representing the method @method.
7295  * Returns NULL and sets @error on error.
7296  */
7297 MonoReflectionMethod*
7298 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7299 {
7300         /*
7301          * We use the same C representation for methods and constructors, but the type 
7302          * name in C# is different.
7303          */
7304         MonoReflectionType *rt;
7305         MonoClass *klass;
7306         MonoReflectionMethod *ret;
7307
7308         mono_error_init (error);
7309
7310         if (method->is_inflated) {
7311                 MonoReflectionGenericMethod *gret;
7312
7313                 if (!refclass)
7314                         refclass = method->klass;
7315                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7316                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7317                         klass = mono_class_get_mono_generic_cmethod_class ();
7318                 } else {
7319                         klass = mono_class_get_mono_generic_method_class ();
7320                 }
7321                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7322                 if (!mono_error_ok (error))
7323                         goto leave;
7324                 gret->method.method = method;
7325
7326                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7327
7328                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7329                 if (!mono_error_ok (error))
7330                     goto leave;
7331
7332                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7333
7334                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7335         }
7336
7337         if (!refclass)
7338                 refclass = method->klass;
7339
7340         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7341         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7342                 klass = mono_class_get_mono_cmethod_class ();
7343         }
7344         else {
7345                 klass = mono_class_get_mono_method_class ();
7346         }
7347         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7348         if (!mono_error_ok (error))
7349                 goto leave;
7350         ret->method = method;
7351
7352         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7353         if (!mono_error_ok (error))
7354                 goto leave;
7355
7356         MONO_OBJECT_SETREF (ret, reftype, rt);
7357
7358         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7359
7360 leave:
7361         g_assert (!mono_error_ok (error));
7362         return NULL;
7363 }
7364
7365 /*
7366  * mono_method_clear_object:
7367  *
7368  *   Clear the cached reflection objects for the dynamic method METHOD.
7369  */
7370 void
7371 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7372 {
7373         MonoClass *klass;
7374         g_assert (method_is_dynamic (method));
7375
7376         klass = method->klass;
7377         while (klass) {
7378                 clear_cached_object (domain, method, klass);
7379                 klass = klass->parent;
7380         }
7381         /* Added by mono_param_get_objects () */
7382         clear_cached_object (domain, &(method->signature), NULL);
7383         klass = method->klass;
7384         while (klass) {
7385                 clear_cached_object (domain, &(method->signature), klass);
7386                 klass = klass->parent;
7387         }
7388 }
7389
7390 /*
7391  * mono_field_get_object:
7392  * @domain: an app domain
7393  * @klass: a type
7394  * @field: a field
7395  *
7396  * Return an System.Reflection.MonoField object representing the field @field
7397  * in class @klass.
7398  */
7399 MonoReflectionField*
7400 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7401 {
7402         MonoError error;
7403         MonoReflectionField *result;
7404         result = mono_field_get_object_checked (domain, klass, field, &error);
7405         mono_error_raise_exception (&error);
7406         return result;
7407 }
7408
7409 /*
7410  * mono_field_get_object_checked:
7411  * @domain: an app domain
7412  * @klass: a type
7413  * @field: a field
7414  * @error: set on error
7415  *
7416  * Return an System.Reflection.MonoField object representing the field @field
7417  * in class @klass. On error, returns NULL and sets @error.
7418  */
7419 MonoReflectionField*
7420 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7421 {
7422         MonoReflectionType *rt;
7423         MonoReflectionField *res;
7424
7425         mono_error_init (error);
7426
7427         CHECK_OBJECT (MonoReflectionField *, field, klass);
7428         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7429         if (!res)
7430                 return NULL;
7431         res->klass = klass;
7432         res->field = field;
7433         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7434
7435         if (is_field_on_inst (field)) {
7436                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7437
7438                 rt = mono_type_get_object_checked (domain, field->type, error);
7439                 if (!mono_error_ok (error))
7440                         return NULL;
7441
7442                 MONO_OBJECT_SETREF (res, type, rt);
7443         } else {
7444                 if (field->type) {
7445                         rt = mono_type_get_object_checked (domain, field->type, error);
7446                         if (!mono_error_ok (error))
7447                                 return NULL;
7448
7449                         MONO_OBJECT_SETREF (res, type, rt);
7450                 }
7451                 res->attrs = mono_field_get_flags (field);
7452         }
7453         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7454 }
7455
7456 /*
7457  * mono_property_get_object:
7458  * @domain: an app domain
7459  * @klass: a type
7460  * @property: a property
7461  *
7462  * Return an System.Reflection.MonoProperty object representing the property @property
7463  * in class @klass.
7464  */
7465 MonoReflectionProperty*
7466 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7467 {
7468         MonoError error;
7469         MonoReflectionProperty *result;
7470         result = mono_property_get_object_checked (domain, klass, property, &error);
7471         mono_error_raise_exception (&error);
7472         return result;
7473 }
7474
7475 /**
7476  * mono_property_get_object:
7477  * @domain: an app domain
7478  * @klass: a type
7479  * @property: a property
7480  * @error: set on error
7481  *
7482  * Return an System.Reflection.MonoProperty object representing the property @property
7483  * in class @klass.  On error returns NULL and sets @error.
7484  */
7485 MonoReflectionProperty*
7486 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7487 {
7488         MonoReflectionProperty *res;
7489
7490         mono_error_init (error);
7491
7492         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7493         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7494         if (!res)
7495                 return NULL;
7496         res->klass = klass;
7497         res->property = property;
7498         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7499 }
7500
7501 /*
7502  * mono_event_get_object:
7503  * @domain: an app domain
7504  * @klass: a type
7505  * @event: a event
7506  *
7507  * Return an System.Reflection.MonoEvent object representing the event @event
7508  * in class @klass.
7509  */
7510 MonoReflectionEvent*
7511 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7512 {
7513         MonoError error;
7514         MonoReflectionEvent *result;
7515         result = mono_event_get_object_checked (domain, klass, event, &error);
7516         mono_error_raise_exception (&error);
7517         return result;
7518 }
7519
7520 /**
7521  * mono_event_get_object_checked:
7522  * @domain: an app domain
7523  * @klass: a type
7524  * @event: a event
7525  * @error: set on error
7526  *
7527  * Return an System.Reflection.MonoEvent object representing the event @event
7528  * in class @klass. On failure sets @error and returns NULL
7529  */
7530 MonoReflectionEvent*
7531 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7532 {
7533         MonoReflectionEvent *res;
7534         MonoReflectionMonoEvent *mono_event;
7535
7536         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7537         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7538         if (!mono_event)
7539                 return NULL;
7540         mono_event->klass = klass;
7541         mono_event->event = event;
7542         res = (MonoReflectionEvent*)mono_event;
7543         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7544 }
7545
7546 /**
7547  * mono_get_reflection_missing_object:
7548  * @domain: Domain where the object lives
7549  *
7550  * Returns the System.Reflection.Missing.Value singleton object
7551  * (of type System.Reflection.Missing).
7552  *
7553  * Used as the value for ParameterInfo.DefaultValue when Optional
7554  * is present
7555  */
7556 static MonoObject *
7557 mono_get_reflection_missing_object (MonoDomain *domain)
7558 {
7559         MonoError error;
7560         MonoObject *obj;
7561         static MonoClassField *missing_value_field = NULL;
7562         
7563         if (!missing_value_field) {
7564                 MonoClass *missing_klass;
7565                 missing_klass = mono_class_get_missing_class ();
7566                 mono_class_init (missing_klass);
7567                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7568                 g_assert (missing_value_field);
7569         }
7570         obj = mono_field_get_value_object_checked (domain, missing_value_field, NULL, &error);
7571         mono_error_assert_ok (&error);
7572         return obj;
7573 }
7574
7575 static MonoObject*
7576 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7577 {
7578         if (!*dbnull)
7579                 *dbnull = mono_get_dbnull_object (domain);
7580         return *dbnull;
7581 }
7582
7583 static MonoObject*
7584 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7585 {
7586         if (!*reflection_missing)
7587                 *reflection_missing = mono_get_reflection_missing_object (domain);
7588         return *reflection_missing;
7589 }
7590
7591 /*
7592  * mono_param_get_objects:
7593  * @domain: an app domain
7594  * @method: a method
7595  *
7596  * Return an System.Reflection.ParameterInfo array object representing the parameters
7597  * in the method @method.
7598  */
7599 MonoArray*
7600 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7601 {
7602         static MonoClass *System_Reflection_ParameterInfo;
7603         static MonoClass *System_Reflection_ParameterInfo_array;
7604         MonoArray *res = NULL;
7605         MonoReflectionMethod *member = NULL;
7606         MonoReflectionParameter *param = NULL;
7607         char **names = NULL, **blobs = NULL;
7608         guint32 *types = NULL;
7609         MonoType *type = NULL;
7610         MonoObject *dbnull = NULL;
7611         MonoObject *missing = NULL;
7612         MonoMarshalSpec **mspecs = NULL;
7613         MonoMethodSignature *sig = NULL;
7614         MonoVTable *pinfo_vtable;
7615         MonoReflectionType *rt;
7616         int i;
7617
7618         mono_error_init (error);
7619         
7620         if (!System_Reflection_ParameterInfo_array) {
7621                 MonoClass *klass;
7622
7623                 klass = mono_class_get_mono_parameter_info_class ();
7624
7625                 mono_memory_barrier ();
7626                 System_Reflection_ParameterInfo = klass; 
7627
7628         
7629                 klass = mono_array_class_get (klass, 1);
7630                 mono_memory_barrier ();
7631                 System_Reflection_ParameterInfo_array = klass;
7632         }
7633
7634         sig = mono_method_signature_checked (method, error);
7635         if (!mono_error_ok (error))
7636                 goto leave;
7637
7638         if (!sig->param_count) {
7639                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, error);
7640                 if (!res)
7641                         goto leave;
7642
7643                 return res;
7644         }
7645
7646         /* Note: the cache is based on the address of the signature into the method
7647          * since we already cache MethodInfos with the method as keys.
7648          */
7649         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7650
7651         member = mono_method_get_object_checked (domain, method, refclass, error);
7652         if (!member)
7653                 goto leave;
7654         names = g_new (char *, sig->param_count);
7655         mono_method_get_param_names (method, (const char **) names);
7656
7657         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7658         mono_method_get_marshal_info (method, mspecs);
7659
7660         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, error);
7661         if (!res)
7662                 goto leave;
7663
7664         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7665         for (i = 0; i < sig->param_count; ++i) {
7666                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, error);
7667                 if (!param)
7668                         goto leave;
7669
7670                 rt = mono_type_get_object_checked (domain, sig->params [i], error);
7671                 if (!rt)
7672                         goto leave;
7673
7674                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7675
7676                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7677
7678                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7679
7680                 param->PositionImpl = i;
7681                 param->AttrsImpl = sig->params [i]->attrs;
7682
7683                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7684                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7685                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7686                         else
7687                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7688                 } else {
7689
7690                         if (!blobs) {
7691                                 blobs = g_new0 (char *, sig->param_count);
7692                                 types = g_new0 (guint32, sig->param_count);
7693                                 get_default_param_value_blobs (method, blobs, types); 
7694                         }
7695
7696                         /* Build MonoType for the type from the Constant Table */
7697                         if (!type)
7698                                 type = g_new0 (MonoType, 1);
7699                         type->type = (MonoTypeEnum)types [i];
7700                         type->data.klass = NULL;
7701                         if (types [i] == MONO_TYPE_CLASS)
7702                                 type->data.klass = mono_defaults.object_class;
7703                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7704                                 /* For enums, types [i] contains the base type */
7705
7706                                         type->type = MONO_TYPE_VALUETYPE;
7707                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7708                         } else
7709                                 type->data.klass = mono_class_from_mono_type (type);
7710
7711                         MonoObject *default_val_obj = mono_get_object_from_blob (domain, type, blobs [i], error);
7712                         if (!is_ok (error))
7713                                 goto leave;
7714                         MONO_OBJECT_SETREF (param, DefaultValueImpl, default_val_obj);
7715
7716                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7717                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7718                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7719                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7720                                 else
7721                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7722                         }
7723                         
7724                 }
7725
7726                 if (mspecs [i + 1]) {
7727                         MonoReflectionMarshalAsAttribute* mobj;
7728                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], error);
7729                         if (!mobj)
7730                                 goto leave;
7731                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7732                 }
7733                 
7734                 mono_array_setref (res, i, param);
7735         }
7736
7737 leave:
7738         g_free (names);
7739         g_free (blobs);
7740         g_free (types);
7741         g_free (type);
7742
7743         if (sig) {
7744                 for (i = sig->param_count; i >= 0; i--) {
7745                         if (mspecs [i])
7746                                 mono_metadata_free_marshal_spec (mspecs [i]);
7747                 }
7748         }
7749         g_free (mspecs);
7750
7751         if (!is_ok (error))
7752                 return NULL;
7753         
7754         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7755 }
7756
7757 MonoArray*
7758 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7759 {
7760         MonoError error;
7761         MonoArray *result = mono_param_get_objects_internal (domain, method, NULL, &error);
7762         mono_error_assert_ok (&error);
7763         return result;
7764 }
7765
7766 /*
7767  * mono_method_body_get_object:
7768  * @domain: an app domain
7769  * @method: a method
7770  *
7771  * Return an System.Reflection.MethodBody object representing the method @method.
7772  */
7773 MonoReflectionMethodBody*
7774 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7775 {
7776         MonoError error;
7777         MonoReflectionMethodBody *result = mono_method_body_get_object_checked (domain, method, &error);
7778         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
7779         return result;
7780 }
7781
7782 /**
7783  * mono_method_body_get_object_checked:
7784  * @domain: an app domain
7785  * @method: a method
7786  * @error: set on error
7787  *
7788  * Return an System.Reflection.MethodBody object representing the
7789  * method @method.  On failure, returns NULL and sets @error.
7790  */
7791 MonoReflectionMethodBody*
7792 mono_method_body_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
7793 {
7794         MonoReflectionMethodBody *ret;
7795         MonoMethodHeader *header;
7796         MonoImage *image;
7797         MonoReflectionType *rt;
7798         guint32 method_rva, local_var_sig_token;
7799         char *ptr;
7800         unsigned char format, flags;
7801         int i;
7802
7803         mono_error_init (error);
7804
7805         /* for compatibility with .net */
7806         if (method_is_dynamic (method)) {
7807                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
7808                 return NULL;
7809         }
7810
7811         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7812
7813         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7814                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7815             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7816                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7817             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7818                 return NULL;
7819
7820         image = method->klass->image;
7821         header = mono_method_get_header_checked (method, error);
7822         return_val_if_nok (error, NULL);
7823
7824         if (!image_is_dynamic (image)) {
7825                 /* Obtain local vars signature token */
7826                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7827                 ptr = mono_image_rva_map (image, method_rva);
7828                 flags = *(const unsigned char *) ptr;
7829                 format = flags & METHOD_HEADER_FORMAT_MASK;
7830                 switch (format){
7831                 case METHOD_HEADER_TINY_FORMAT:
7832                         local_var_sig_token = 0;
7833                         break;
7834                 case METHOD_HEADER_FAT_FORMAT:
7835                         ptr += 2;
7836                         ptr += 2;
7837                         ptr += 4;
7838                         local_var_sig_token = read32 (ptr);
7839                         break;
7840                 default:
7841                         g_assert_not_reached ();
7842                 }
7843         } else
7844                 local_var_sig_token = 0; //FIXME
7845
7846         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), error);
7847         if (!is_ok (error))
7848                 goto fail;
7849
7850         ret->init_locals = header->init_locals;
7851         ret->max_stack = header->max_stack;
7852         ret->local_var_sig_token = local_var_sig_token;
7853         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7854         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7855
7856         /* Locals */
7857         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7858         for (i = 0; i < header->num_locals; ++i) {
7859                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), error);
7860                 if (!is_ok (error))
7861                         goto fail;
7862
7863                 rt = mono_type_get_object_checked (domain, header->locals [i], error);
7864                 if (!is_ok (error))
7865                         goto fail;
7866
7867                 MONO_OBJECT_SETREF (info, local_type, rt);
7868
7869                 info->is_pinned = header->locals [i]->pinned;
7870                 info->local_index = i;
7871                 mono_array_setref (ret->locals, i, info);
7872         }
7873
7874         /* Exceptions */
7875         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7876         for (i = 0; i < header->num_clauses; ++i) {
7877                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), error);
7878                 if (!is_ok (error))
7879                         goto fail;
7880                 MonoExceptionClause *clause = &header->clauses [i];
7881
7882                 info->flags = clause->flags;
7883                 info->try_offset = clause->try_offset;
7884                 info->try_length = clause->try_len;
7885                 info->handler_offset = clause->handler_offset;
7886                 info->handler_length = clause->handler_len;
7887                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7888                         info->filter_offset = clause->data.filter_offset;
7889                 else if (clause->data.catch_class) {
7890                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, error);
7891                         if (!is_ok (error))
7892                                 goto fail;
7893
7894                         MONO_OBJECT_SETREF (info, catch_type, rt);
7895                 }
7896
7897                 mono_array_setref (ret->clauses, i, info);
7898         }
7899
7900         mono_metadata_free_mh (header);
7901         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7902         return ret;
7903
7904 fail:
7905         mono_metadata_free_mh (header);
7906         return NULL;
7907 }
7908
7909 /**
7910  * mono_get_dbnull_object:
7911  * @domain: Domain where the object lives
7912  *
7913  * Returns the System.DBNull.Value singleton object
7914  *
7915  * Used as the value for ParameterInfo.DefaultValue 
7916  */
7917 MonoObject *
7918 mono_get_dbnull_object (MonoDomain *domain)
7919 {
7920         MonoError error;
7921         MonoObject *obj;
7922         static MonoClassField *dbnull_value_field = NULL;
7923         
7924         if (!dbnull_value_field) {
7925                 MonoClass *dbnull_klass;
7926                 dbnull_klass = mono_class_get_dbnull_class ();
7927                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7928                 g_assert (dbnull_value_field);
7929         }
7930         obj = mono_field_get_value_object_checked (domain, dbnull_value_field, NULL, &error);
7931         mono_error_assert_ok (&error);
7932         return obj;
7933 }
7934
7935 static void
7936 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7937 {
7938         guint32 param_index, i, lastp, crow = 0;
7939         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7940         gint32 idx;
7941
7942         MonoClass *klass = method->klass;
7943         MonoImage *image = klass->image;
7944         MonoMethodSignature *methodsig = mono_method_signature (method);
7945
7946         MonoTableInfo *constt;
7947         MonoTableInfo *methodt;
7948         MonoTableInfo *paramt;
7949
7950         if (!methodsig->param_count)
7951                 return;
7952
7953         mono_class_init (klass);
7954
7955         if (image_is_dynamic (klass->image)) {
7956                 MonoReflectionMethodAux *aux;
7957                 if (method->is_inflated)
7958                         method = ((MonoMethodInflated*)method)->declaring;
7959                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7960                 if (aux && aux->param_defaults) {
7961                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7962                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7963                 }
7964                 return;
7965         }
7966
7967         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7968         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7969         constt = &image->tables [MONO_TABLE_CONSTANT];
7970
7971         idx = mono_method_get_index (method) - 1;
7972         g_assert (idx != -1);
7973
7974         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7975         if (idx + 1 < methodt->rows)
7976                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7977         else
7978                 lastp = paramt->rows + 1;
7979
7980         for (i = param_index; i < lastp; ++i) {
7981                 guint32 paramseq;
7982
7983                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7984                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7985
7986                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7987                         continue;
7988
7989                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7990                 if (!crow) {
7991                         continue;
7992                 }
7993         
7994                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7995                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7996                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7997         }
7998
7999         return;
8000 }
8001
8002 MonoObject *
8003 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob, MonoError *error)
8004 {
8005         void *retval;
8006         MonoClass *klass;
8007         MonoObject *object;
8008         MonoType *basetype = type;
8009
8010         mono_error_init (error);
8011
8012         if (!blob)
8013                 return NULL;
8014         
8015         klass = mono_class_from_mono_type (type);
8016         if (klass->valuetype) {
8017                 object = mono_object_new_checked (domain, klass, error);
8018                 return_val_if_nok (error, NULL);
8019                 retval = ((gchar *) object + sizeof (MonoObject));
8020                 if (klass->enumtype)
8021                         basetype = mono_class_enum_basetype (klass);
8022         } else {
8023                 retval = &object;
8024         }
8025                         
8026         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
8027                 return object;
8028         else
8029                 return NULL;
8030 }
8031
8032 static int
8033 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
8034         int found_sep;
8035         char *s;
8036         gboolean quoted = FALSE;
8037
8038         memset (assembly, 0, sizeof (MonoAssemblyName));
8039         assembly->culture = "";
8040         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8041
8042         if (*p == '"') {
8043                 quoted = TRUE;
8044                 p++;
8045         }
8046         assembly->name = p;
8047         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8048                 p++;
8049         if (quoted) {
8050                 if (*p != '"')
8051                         return 1;
8052                 *p = 0;
8053                 p++;
8054         }
8055         if (*p != ',')
8056                 return 1;
8057         *p = 0;
8058         /* Remove trailing whitespace */
8059         s = p - 1;
8060         while (*s && g_ascii_isspace (*s))
8061                 *s-- = 0;
8062         p ++;
8063         while (g_ascii_isspace (*p))
8064                 p++;
8065         while (*p) {
8066                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8067                         p += 8;
8068                         assembly->major = strtoul (p, &s, 10);
8069                         if (s == p || *s != '.')
8070                                 return 1;
8071                         p = ++s;
8072                         assembly->minor = strtoul (p, &s, 10);
8073                         if (s == p || *s != '.')
8074                                 return 1;
8075                         p = ++s;
8076                         assembly->build = strtoul (p, &s, 10);
8077                         if (s == p || *s != '.')
8078                                 return 1;
8079                         p = ++s;
8080                         assembly->revision = strtoul (p, &s, 10);
8081                         if (s == p)
8082                                 return 1;
8083                         p = s;
8084                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8085                         p += 8;
8086                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8087                                 assembly->culture = "";
8088                                 p += 7;
8089                         } else {
8090                                 assembly->culture = p;
8091                                 while (*p && *p != ',') {
8092                                         p++;
8093                                 }
8094                         }
8095                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8096                         p += 15;
8097                         if (strncmp (p, "null", 4) == 0) {
8098                                 p += 4;
8099                         } else {
8100                                 int len;
8101                                 gchar *start = p;
8102                                 while (*p && *p != ',') {
8103                                         p++;
8104                                 }
8105                                 len = (p - start + 1);
8106                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8107                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8108                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8109                         }
8110                 } else {
8111                         while (*p && *p != ',')
8112                                 p++;
8113                 }
8114                 found_sep = 0;
8115                 while (g_ascii_isspace (*p) || *p == ',') {
8116                         *p++ = 0;
8117                         found_sep = 1;
8118                         continue;
8119                 }
8120                 /* failed */
8121                 if (!found_sep)
8122                         return 1;
8123         }
8124
8125         return 0;
8126 }
8127
8128 /*
8129  * mono_reflection_parse_type:
8130  * @name: type name
8131  *
8132  * Parse a type name as accepted by the GetType () method and output the info
8133  * extracted in the info structure.
8134  * the name param will be mangled, so, make a copy before passing it to this function.
8135  * The fields in info will be valid until the memory pointed to by name is valid.
8136  *
8137  * See also mono_type_get_name () below.
8138  *
8139  * Returns: 0 on parse error.
8140  */
8141 static int
8142 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8143                              MonoTypeNameParse *info)
8144 {
8145         char *start, *p, *w, *last_point, *startn;
8146         int in_modifiers = 0;
8147         int isbyref = 0, rank = 0, isptr = 0;
8148
8149         start = p = w = name;
8150
8151         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8152         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8153         info->name = info->name_space = NULL;
8154         info->nested = NULL;
8155         info->modifiers = NULL;
8156         info->type_arguments = NULL;
8157
8158         /* last_point separates the namespace from the name */
8159         last_point = NULL;
8160         /* Skips spaces */
8161         while (*p == ' ') p++, start++, w++, name++;
8162
8163         while (*p) {
8164                 switch (*p) {
8165                 case '+':
8166                         *p = 0; /* NULL terminate the name */
8167                         startn = p + 1;
8168                         info->nested = g_list_append (info->nested, startn);
8169                         /* we have parsed the nesting namespace + name */
8170                         if (info->name)
8171                                 break;
8172                         if (last_point) {
8173                                 info->name_space = start;
8174                                 *last_point = 0;
8175                                 info->name = last_point + 1;
8176                         } else {
8177                                 info->name_space = (char *)"";
8178                                 info->name = start;
8179                         }
8180                         break;
8181                 case '.':
8182                         last_point = p;
8183                         break;
8184                 case '\\':
8185                         ++p;
8186                         break;
8187                 case '&':
8188                 case '*':
8189                 case '[':
8190                 case ',':
8191                 case ']':
8192                         in_modifiers = 1;
8193                         break;
8194                 default:
8195                         break;
8196                 }
8197                 if (in_modifiers)
8198                         break;
8199                 // *w++ = *p++;
8200                 p++;
8201         }
8202         
8203         if (!info->name) {
8204                 if (last_point) {
8205                         info->name_space = start;
8206                         *last_point = 0;
8207                         info->name = last_point + 1;
8208                 } else {
8209                         info->name_space = (char *)"";
8210                         info->name = start;
8211                 }
8212         }
8213         while (*p) {
8214                 switch (*p) {
8215                 case '&':
8216                         if (isbyref) /* only one level allowed by the spec */
8217                                 return 0;
8218                         isbyref = 1;
8219                         isptr = 0;
8220                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8221                         *p++ = 0;
8222                         break;
8223                 case '*':
8224                         if (isbyref) /* pointer to ref not okay */
8225                                 return 0;
8226                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8227                         isptr = 1;
8228                         *p++ = 0;
8229                         break;
8230                 case '[':
8231                         if (isbyref) /* array of ref and generic ref are not okay */
8232                                 return 0;
8233                         //Decide if it's an array of a generic argument list
8234                         *p++ = 0;
8235
8236                         if (!*p) //XXX test
8237                                 return 0;
8238                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8239                                 isptr = 0;
8240                                 rank = 1;
8241                                 while (*p) {
8242                                         if (*p == ']')
8243                                                 break;
8244                                         if (*p == ',')
8245                                                 rank++;
8246                                         else if (*p == '*') /* '*' means unknown lower bound */
8247                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8248                                         else
8249                                                 return 0;
8250                                         ++p;
8251                                 }
8252                                 if (*p++ != ']')
8253                                         return 0;
8254                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8255                         } else {
8256                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8257                                         return 0;
8258                                 isptr = 0;
8259                                 info->type_arguments = g_ptr_array_new ();
8260                                 while (*p) {
8261                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8262                                         gboolean fqname = FALSE;
8263
8264                                         g_ptr_array_add (info->type_arguments, subinfo);
8265
8266                                         while (*p == ' ') p++;
8267                                         if (*p == '[') {
8268                                                 p++;
8269                                                 fqname = TRUE;
8270                                         }
8271
8272                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8273                                                 return 0;
8274
8275                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8276                                         if (fqname && (*p != ']')) {
8277                                                 char *aname;
8278
8279                                                 if (*p != ',')
8280                                                         return 0;
8281                                                 *p++ = 0;
8282
8283                                                 aname = p;
8284                                                 while (*p && (*p != ']'))
8285                                                         p++;
8286
8287                                                 if (*p != ']')
8288                                                         return 0;
8289
8290                                                 *p++ = 0;
8291                                                 while (*aname) {
8292                                                         if (g_ascii_isspace (*aname)) {
8293                                                                 ++aname;
8294                                                                 continue;
8295                                                         }
8296                                                         break;
8297                                                 }
8298                                                 if (!*aname ||
8299                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8300                                                         return 0;
8301                                         } else if (fqname && (*p == ']')) {
8302                                                 *p++ = 0;
8303                                         }
8304                                         if (*p == ']') {
8305                                                 *p++ = 0;
8306                                                 break;
8307                                         } else if (!*p) {
8308                                                 return 0;
8309                                         }
8310                                         *p++ = 0;
8311                                 }
8312                         }
8313                         break;
8314                 case ']':
8315                         if (is_recursed)
8316                                 goto end;
8317                         return 0;
8318                 case ',':
8319                         if (is_recursed)
8320                                 goto end;
8321                         *p++ = 0;
8322                         while (*p) {
8323                                 if (g_ascii_isspace (*p)) {
8324                                         ++p;
8325                                         continue;
8326                                 }
8327                                 break;
8328                         }
8329                         if (!*p)
8330                                 return 0; /* missing assembly name */
8331                         if (!assembly_name_to_aname (&info->assembly, p))
8332                                 return 0;
8333                         break;
8334                 default:
8335                         return 0;
8336                 }
8337                 if (info->assembly.name)
8338                         break;
8339         }
8340         // *w = 0; /* terminate class name */
8341  end:
8342         if (!info->name || !*info->name)
8343                 return 0;
8344         if (endptr)
8345                 *endptr = p;
8346         /* add other consistency checks */
8347         return 1;
8348 }
8349
8350
8351 /**
8352  * mono_identifier_unescape_type_name_chars:
8353  * @identifier: the display name of a mono type
8354  *
8355  * Returns:
8356  *  The name in internal form, that is without escaping backslashes.
8357  *
8358  *  The string is modified in place!
8359  */
8360 char*
8361 mono_identifier_unescape_type_name_chars(char* identifier)
8362 {
8363         char *w, *r;
8364         if (!identifier)
8365                 return NULL;
8366         for (w = r = identifier; *r != 0; r++)
8367         {
8368                 char c = *r;
8369                 if (c == '\\') {
8370                         r++;
8371                         if (*r == 0)
8372                                 break;
8373                         c = *r;
8374                 }
8375                 *w = c;
8376                 w++;
8377         }
8378         if (w != r)
8379                 *w = 0;
8380         return identifier;
8381 }
8382
8383 void
8384 mono_identifier_unescape_info (MonoTypeNameParse* info);
8385
8386 static void
8387 unescape_each_type_argument(void* data, void* user_data)
8388 {
8389         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8390         mono_identifier_unescape_info (info);
8391 }
8392
8393 static void
8394 unescape_each_nested_name (void* data, void* user_data)
8395 {
8396         char* nested_name = (char*) data;
8397         mono_identifier_unescape_type_name_chars(nested_name);
8398 }
8399
8400 /**
8401  * mono_identifier_unescape_info:
8402  *
8403  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8404  *
8405  * Returns: nothing.
8406  *
8407  * Destructively updates the info by unescaping the identifiers that
8408  * comprise the type namespace, name, nested types (if any) and
8409  * generic type arguments (if any).
8410  *
8411  * The resulting info has the names in internal form.
8412  *
8413  */
8414 void
8415 mono_identifier_unescape_info (MonoTypeNameParse *info)
8416 {
8417         if (!info)
8418                 return;
8419         mono_identifier_unescape_type_name_chars(info->name_space);
8420         mono_identifier_unescape_type_name_chars(info->name);
8421         // but don't escape info->assembly
8422         if (info->type_arguments)
8423                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8424         if (info->nested)
8425                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8426 }
8427
8428 int
8429 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8430 {
8431         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8432         if (ok) {
8433                 mono_identifier_unescape_info (info);
8434         }
8435         return ok;
8436 }
8437
8438 static MonoType*
8439 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase, MonoError *error)
8440 {
8441         gboolean type_resolve = FALSE;
8442         MonoType *type;
8443         MonoImage *rootimage = image;
8444
8445         mono_error_init (error);
8446
8447         if (info->assembly.name) {
8448                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8449                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8450                         /* 
8451                          * This could happen in the AOT compiler case when the search hook is not
8452                          * installed.
8453                          */
8454                         assembly = image->assembly;
8455                 if (!assembly) {
8456                         /* then we must load the assembly ourselve - see #60439 */
8457                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8458                         if (!assembly)
8459                                 return NULL;
8460                 }
8461                 image = assembly->image;
8462         } else if (!image) {
8463                 image = mono_defaults.corlib;
8464         }
8465
8466         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8467         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8468                 mono_error_cleanup (error);
8469                 image = mono_defaults.corlib;
8470                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve, error);
8471         }
8472
8473         return type;
8474 }
8475
8476 /**
8477  * mono_reflection_get_type_internal:
8478  *
8479  * Returns: may return NULL on success, sets error on failure.
8480  */
8481 static MonoType*
8482 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8483 {
8484         MonoClass *klass;
8485         GList *mod;
8486         int modval;
8487         gboolean bounded = FALSE;
8488         
8489         mono_error_init (error);
8490         if (!image)
8491                 image = mono_defaults.corlib;
8492
8493         if (!rootimage)
8494                 rootimage = mono_defaults.corlib;
8495
8496         if (ignorecase)
8497                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8498         else
8499                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8500
8501         if (!klass)
8502                 return NULL;
8503
8504         for (mod = info->nested; mod; mod = mod->next) {
8505                 gpointer iter = NULL;
8506                 MonoClass *parent;
8507
8508                 parent = klass;
8509                 mono_class_init (parent);
8510
8511                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8512                         char *lastp;
8513                         char *nested_name, *nested_nspace;
8514                         gboolean match = TRUE;
8515
8516                         lastp = strrchr ((const char *)mod->data, '.');
8517                         if (lastp) {
8518                                 /* Nested classes can have namespaces */
8519                                 int nspace_len;
8520
8521                                 nested_name = g_strdup (lastp + 1);
8522                                 nspace_len = lastp - (char*)mod->data;
8523                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8524                                 memcpy (nested_nspace, mod->data, nspace_len);
8525                                 nested_nspace [nspace_len] = '\0';
8526
8527                         } else {
8528                                 nested_name = (char *)mod->data;
8529                                 nested_nspace = NULL;
8530                         }
8531
8532                         if (nested_nspace) {
8533                                 if (ignorecase) {
8534                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8535                                                 match = FALSE;
8536                                 } else {
8537                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8538                                                 match = FALSE;
8539                                 }
8540                         }
8541                         if (match) {
8542                                 if (ignorecase) {
8543                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8544                                                 match = FALSE;
8545                                 } else {
8546                                         if (strcmp (klass->name, nested_name) != 0)
8547                                                 match = FALSE;
8548                                 }
8549                         }
8550                         if (lastp) {
8551                                 g_free (nested_name);
8552                                 g_free (nested_nspace);
8553                         }
8554                         if (match)
8555                                 break;
8556                 }
8557
8558                 if (!klass)
8559                         break;
8560         }
8561         if (!klass)
8562                 return NULL;
8563
8564         if (info->type_arguments) {
8565                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8566                 MonoReflectionType *the_type;
8567                 MonoType *instance;
8568                 int i;
8569
8570                 for (i = 0; i < info->type_arguments->len; i++) {
8571                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8572
8573                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase, error);
8574                         if (!type_args [i]) {
8575                                 g_free (type_args);
8576                                 return NULL;
8577                         }
8578                 }
8579
8580                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8581                 if (!the_type)
8582                         return NULL;
8583
8584                 instance = mono_reflection_bind_generic_parameters (
8585                         the_type, info->type_arguments->len, type_args, error);
8586
8587                 g_free (type_args);
8588                 if (!instance)
8589                         return NULL;
8590
8591                 klass = mono_class_from_mono_type (instance);
8592         }
8593
8594         for (mod = info->modifiers; mod; mod = mod->next) {
8595                 modval = GPOINTER_TO_UINT (mod->data);
8596                 if (!modval) { /* byref: must be last modifier */
8597                         return &klass->this_arg;
8598                 } else if (modval == -1) {
8599                         klass = mono_ptr_class_get (&klass->byval_arg);
8600                 } else if (modval == -2) {
8601                         bounded = TRUE;
8602                 } else { /* array rank */
8603                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8604                 }
8605         }
8606
8607         return &klass->byval_arg;
8608 }
8609
8610 /*
8611  * mono_reflection_get_type:
8612  * @image: a metadata context
8613  * @info: type description structure
8614  * @ignorecase: flag for case-insensitive string compares
8615  * @type_resolve: whenever type resolve was already tried
8616  *
8617  * Build a MonoType from the type description in @info.
8618  * 
8619  */
8620
8621 MonoType*
8622 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8623         MonoError error;
8624         MonoType *result = mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, &error);
8625         mono_error_cleanup (&error);
8626         return result;
8627 }
8628
8629 /**
8630  * mono_reflection_get_type_checked:
8631  * @image: a metadata context
8632  * @info: type description structure
8633  * @ignorecase: flag for case-insensitive string compares
8634  * @type_resolve: whenever type resolve was already tried
8635  * @error: set on error.
8636  *
8637  * Build a MonoType from the type description in @info. On failure returns NULL and sets @error.
8638  *
8639  */
8640 MonoType*
8641 mono_reflection_get_type_checked (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error) {
8642         mono_error_init (error);
8643         return mono_reflection_get_type_with_rootimage (image, image, info, ignorecase, type_resolve, error);
8644 }
8645
8646
8647 static MonoType*
8648 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8649 {
8650         MonoReflectionAssemblyBuilder *abuilder;
8651         MonoType *type;
8652         int i;
8653
8654         mono_error_init (error);
8655         g_assert (assembly_is_dynamic (assembly));
8656         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8657         if (!abuilder)
8658                 return NULL;
8659
8660         /* Enumerate all modules */
8661
8662         type = NULL;
8663         if (abuilder->modules) {
8664                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8665                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8666                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8667                         if (type)
8668                                 break;
8669                         if (!mono_error_ok (error))
8670                                 return NULL;
8671                 }
8672         }
8673
8674         if (!type && abuilder->loaded_modules) {
8675                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8676                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8677                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8678                         if (type)
8679                                 break;
8680                         if (!mono_error_ok (error))
8681                                 return NULL;
8682                 }
8683         }
8684
8685         return type;
8686 }
8687         
8688 MonoType*
8689 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve, MonoError *error)
8690 {
8691         MonoType *type;
8692         MonoReflectionAssembly *assembly;
8693         GString *fullName;
8694         GList *mod;
8695
8696         mono_error_init (error);
8697
8698         if (image && image_is_dynamic (image))
8699                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, error);
8700         else {
8701                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, error);
8702         }
8703         return_val_if_nok (error, NULL);
8704
8705         if (type)
8706                 return type;
8707         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8708                 return NULL;
8709
8710         if (type_resolve) {
8711                 if (*type_resolve) 
8712                         return NULL;
8713                 else
8714                         *type_resolve = TRUE;
8715         }
8716         
8717         /* Reconstruct the type name */
8718         fullName = g_string_new ("");
8719         if (info->name_space && (info->name_space [0] != '\0'))
8720                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8721         else
8722                 g_string_printf (fullName, "%s", info->name);
8723         for (mod = info->nested; mod; mod = mod->next)
8724                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8725
8726         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, error);
8727         if (!is_ok (error)) {
8728                 g_string_free (fullName, TRUE);
8729                 return NULL;
8730         }
8731
8732         if (assembly) {
8733                 if (assembly_is_dynamic (assembly->assembly))
8734                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8735                                                                           info, ignorecase, error);
8736                 else
8737                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8738                                                                   info, ignorecase, error);
8739         }
8740         g_string_free (fullName, TRUE);
8741         return_val_if_nok (error, NULL);
8742         return type;
8743 }
8744
8745 void
8746 mono_reflection_free_type_info (MonoTypeNameParse *info)
8747 {
8748         g_list_free (info->modifiers);
8749         g_list_free (info->nested);
8750
8751         if (info->type_arguments) {
8752                 int i;
8753
8754                 for (i = 0; i < info->type_arguments->len; i++) {
8755                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8756
8757                         mono_reflection_free_type_info (subinfo);
8758                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8759                         g_free (subinfo);
8760                 }
8761
8762                 g_ptr_array_free (info->type_arguments, TRUE);
8763         }
8764 }
8765
8766 /*
8767  * mono_reflection_type_from_name:
8768  * @name: type name.
8769  * @image: a metadata context (can be NULL).
8770  *
8771  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8772  * it defaults to get the type from @image or, if @image is NULL or loading
8773  * from it fails, uses corlib.
8774  * 
8775  */
8776 MonoType*
8777 mono_reflection_type_from_name (char *name, MonoImage *image)
8778 {
8779         MonoError error;
8780         MonoType  *result = mono_reflection_type_from_name_checked (name, image, &error);
8781         mono_error_cleanup (&error);
8782         return result;
8783 }
8784
8785 /**
8786  * mono_reflection_type_from_name_checked:
8787  * @name: type name.
8788  * @image: a metadata context (can be NULL).
8789  * @error: set on errror.
8790  *
8791  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8792  * it defaults to get the type from @image or, if @image is NULL or loading
8793  * from it fails, uses corlib.  On failure returns NULL and sets @error.
8794  * 
8795  */
8796 MonoType*
8797 mono_reflection_type_from_name_checked (char *name, MonoImage *image, MonoError *error)
8798 {
8799         MonoType *type = NULL;
8800         MonoTypeNameParse info;
8801         char *tmp;
8802
8803         mono_error_init (error);
8804         /* Make a copy since parse_type modifies its argument */
8805         tmp = g_strdup (name);
8806         
8807         /*g_print ("requested type %s\n", str);*/
8808         if (mono_reflection_parse_type (tmp, &info)) {
8809                 type = _mono_reflection_get_type_from_info (&info, image, FALSE, error);
8810                 if (!is_ok (error)) {
8811                         g_free (tmp);
8812                         mono_reflection_free_type_info (&info);
8813                         return NULL;
8814                 }
8815         }
8816
8817         g_free (tmp);
8818         mono_reflection_free_type_info (&info);
8819         return type;
8820 }
8821
8822 /*
8823  * mono_reflection_get_token:
8824  *
8825  *   Return the metadata token of OBJ which should be an object
8826  * representing a metadata element.
8827  */
8828 guint32
8829 mono_reflection_get_token (MonoObject *obj)
8830 {
8831         MonoError error;
8832         guint32 result = mono_reflection_get_token_checked (obj, &error);
8833         mono_error_assert_ok (&error);
8834         return result;
8835 }
8836
8837 /**
8838  * mono_reflection_get_token_checked:
8839  * @obj: the object
8840  * @error: set on error
8841  *
8842  *   Return the metadata token of @obj which should be an object
8843  * representing a metadata element.  On failure sets @error.
8844  */
8845 guint32
8846 mono_reflection_get_token_checked (MonoObject *obj, MonoError *error)
8847 {
8848         MonoClass *klass;
8849         guint32 token = 0;
8850
8851         mono_error_init (error);
8852
8853         klass = obj->vtable->klass;
8854
8855         if (strcmp (klass->name, "MethodBuilder") == 0) {
8856                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8857
8858                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8859         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8860                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8861
8862                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8863         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8864                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8865
8866                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8867         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8868                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8869                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8870         } else if (strcmp (klass->name, "MonoType") == 0) {
8871                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
8872                 return_val_if_nok (error, 0);
8873                 MonoClass *mc = mono_class_from_mono_type (type);
8874                 if (!mono_class_init (mc)) {
8875                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
8876                         return 0;
8877                 }
8878
8879                 token = mc->type_token;
8880         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8881                    strcmp (klass->name, "MonoMethod") == 0 ||
8882                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8883                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8884                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8885                 if (m->method->is_inflated) {
8886                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8887                         return inflated->declaring->token;
8888                 } else {
8889                         token = m->method->token;
8890                 }
8891         } else if (strcmp (klass->name, "MonoField") == 0) {
8892                 MonoReflectionField *f = (MonoReflectionField*)obj;
8893
8894                 if (is_field_on_inst (f->field)) {
8895                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8896
8897                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8898                                 int field_index = f->field - dgclass->fields;
8899                                 MonoObject *obj;
8900
8901                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8902                                 obj = dgclass->field_objects [field_index];
8903                                 return mono_reflection_get_token_checked (obj, error);
8904                         }
8905                 }
8906                 token = mono_class_get_field_token (f->field);
8907         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8908                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8909
8910                 token = mono_class_get_property_token (p->property);
8911         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8912                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8913
8914                 token = mono_class_get_event_token (p->event);
8915         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8916                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8917                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8918                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8919
8920                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8921         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8922                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8923
8924                 token = m->token;
8925         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8926                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8927         } else {
8928                 mono_error_set_not_implemented (error, "MetadataToken is not supported for type '%s.%s'",
8929                                                 klass->name_space, klass->name);
8930                 return 0;
8931         }
8932
8933         return token;
8934 }
8935
8936 static MonoClass*
8937 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8938 {
8939         char *n;
8940         MonoType *t;
8941         int slen = mono_metadata_decode_value (p, &p);
8942
8943         mono_error_init (error);
8944
8945         n = (char *)g_memdup (p, slen + 1);
8946         n [slen] = 0;
8947         t = mono_reflection_type_from_name_checked (n, image, error);
8948         if (!t) {
8949                 char *msg = g_strdup (mono_error_get_message (error));
8950                 mono_error_cleanup (error);
8951                 /* We don't free n, it's consumed by mono_error */
8952                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute: %s", n, msg);
8953                 g_free (msg);
8954                 return NULL;
8955         }
8956         g_free (n);
8957         p += slen;
8958         *end = p;
8959         return mono_class_from_mono_type (t);
8960 }
8961
8962 static void*
8963 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8964 {
8965         int slen, type = t->type;
8966         MonoClass *tklass = t->data.klass;
8967
8968         mono_error_init (error);
8969
8970 handle_enum:
8971         switch (type) {
8972         case MONO_TYPE_U1:
8973         case MONO_TYPE_I1:
8974         case MONO_TYPE_BOOLEAN: {
8975                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8976                 *bval = *p;
8977                 *end = p + 1;
8978                 return bval;
8979         }
8980         case MONO_TYPE_CHAR:
8981         case MONO_TYPE_U2:
8982         case MONO_TYPE_I2: {
8983                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8984                 *val = read16 (p);
8985                 *end = p + 2;
8986                 return val;
8987         }
8988 #if SIZEOF_VOID_P == 4
8989         case MONO_TYPE_U:
8990         case MONO_TYPE_I:
8991 #endif
8992         case MONO_TYPE_R4:
8993         case MONO_TYPE_U4:
8994         case MONO_TYPE_I4: {
8995                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8996                 *val = read32 (p);
8997                 *end = p + 4;
8998                 return val;
8999         }
9000 #if SIZEOF_VOID_P == 8
9001         case MONO_TYPE_U: /* error out instead? this should probably not happen */
9002         case MONO_TYPE_I:
9003 #endif
9004         case MONO_TYPE_U8:
9005         case MONO_TYPE_I8: {
9006                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9007                 *val = read64 (p);
9008                 *end = p + 8;
9009                 return val;
9010         }
9011         case MONO_TYPE_R8: {
9012                 double *val = (double *)g_malloc (sizeof (double));
9013                 readr8 (p, val);
9014                 *end = p + 8;
9015                 return val;
9016         }
9017         case MONO_TYPE_VALUETYPE:
9018                 if (t->data.klass->enumtype) {
9019                         type = mono_class_enum_basetype (t->data.klass)->type;
9020                         goto handle_enum;
9021                 } else {
9022                         MonoClass *k =  t->data.klass;
9023                         
9024                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
9025                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
9026                                 *val = read64 (p);
9027                                 *end = p + 8;
9028                                 return val;
9029                         }
9030                 }
9031                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
9032                 break;
9033                 
9034         case MONO_TYPE_STRING:
9035                 if (*p == (char)0xFF) {
9036                         *end = p + 1;
9037                         return NULL;
9038                 }
9039                 slen = mono_metadata_decode_value (p, &p);
9040                 *end = p + slen;
9041                 return mono_string_new_len (mono_domain_get (), p, slen);
9042         case MONO_TYPE_CLASS: {
9043                 MonoReflectionType *rt;
9044                 char *n;
9045                 MonoType *t;
9046                 if (*p == (char)0xFF) {
9047                         *end = p + 1;
9048                         return NULL;
9049                 }
9050 handle_type:
9051                 slen = mono_metadata_decode_value (p, &p);
9052                 n = (char *)g_memdup (p, slen + 1);
9053                 n [slen] = 0;
9054                 t = mono_reflection_type_from_name_checked (n, image, error);
9055                 if (!t) {
9056                         char *msg = g_strdup (mono_error_get_message (error));
9057                         mono_error_cleanup (error);
9058                         /* We don't free n, it's consumed by mono_error */
9059                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %msg", n, msg);
9060                         g_free (msg);
9061                         return NULL;
9062                 }
9063                 g_free (n);
9064                 *end = p + slen;
9065
9066                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
9067                 if (!mono_error_ok (error))
9068                         return NULL;
9069
9070                 return rt;
9071         }
9072         case MONO_TYPE_OBJECT: {
9073                 char subt = *p++;
9074                 MonoObject *obj;
9075                 MonoClass *subc = NULL;
9076                 void *val;
9077
9078                 if (subt == 0x50) {
9079                         goto handle_type;
9080                 } else if (subt == 0x0E) {
9081                         type = MONO_TYPE_STRING;
9082                         goto handle_enum;
9083                 } else if (subt == 0x1D) {
9084                         MonoType simple_type = {{0}};
9085                         int etype = *p;
9086                         p ++;
9087
9088                         type = MONO_TYPE_SZARRAY;
9089                         if (etype == 0x50) {
9090                                 tklass = mono_defaults.systemtype_class;
9091                         } else if (etype == 0x55) {
9092                                 tklass = load_cattr_enum_type (image, p, &p, error);
9093                                 if (!mono_error_ok (error))
9094                                         return NULL;
9095                         } else {
9096                                 if (etype == 0x51)
9097                                         /* See Partition II, Appendix B3 */
9098                                         etype = MONO_TYPE_OBJECT;
9099                                 simple_type.type = (MonoTypeEnum)etype;
9100                                 tklass = mono_class_from_mono_type (&simple_type);
9101                         }
9102                         goto handle_enum;
9103                 } else if (subt == 0x55) {
9104                         char *n;
9105                         MonoType *t;
9106                         slen = mono_metadata_decode_value (p, &p);
9107                         n = (char *)g_memdup (p, slen + 1);
9108                         n [slen] = 0;
9109                         t = mono_reflection_type_from_name_checked (n, image, error);
9110                         if (!t) {
9111                                 char *msg = g_strdup (mono_error_get_message (error));
9112                                 mono_error_cleanup (error);
9113                                 /* We don't free n, it's consumed by mono_error */
9114                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute: %s", n, msg);
9115                                 g_free (msg);
9116                                 return NULL;
9117                         }
9118                         g_free (n);
9119                         p += slen;
9120                         subc = mono_class_from_mono_type (t);
9121                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9122                         MonoType simple_type = {{0}};
9123                         simple_type.type = (MonoTypeEnum)subt;
9124                         subc = mono_class_from_mono_type (&simple_type);
9125                 } else {
9126                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9127                 }
9128                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9129                 obj = NULL;
9130                 if (mono_error_ok (error)) {
9131                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9132                         g_assert (!subc->has_references);
9133                         if (mono_error_ok (error))
9134                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9135                 }
9136
9137                 g_free (val);
9138                 return obj;
9139         }
9140         case MONO_TYPE_SZARRAY: {
9141                 MonoArray *arr;
9142                 guint32 i, alen, basetype;
9143                 alen = read32 (p);
9144                 p += 4;
9145                 if (alen == 0xffffffff) {
9146                         *end = p;
9147                         return NULL;
9148                 }
9149                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9150                 basetype = tklass->byval_arg.type;
9151                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9152                         basetype = mono_class_enum_basetype (tklass)->type;
9153                 switch (basetype)
9154                 {
9155                         case MONO_TYPE_U1:
9156                         case MONO_TYPE_I1:
9157                         case MONO_TYPE_BOOLEAN:
9158                                 for (i = 0; i < alen; i++) {
9159                                         MonoBoolean val = *p++;
9160                                         mono_array_set (arr, MonoBoolean, i, val);
9161                                 }
9162                                 break;
9163                         case MONO_TYPE_CHAR:
9164                         case MONO_TYPE_U2:
9165                         case MONO_TYPE_I2:
9166                                 for (i = 0; i < alen; i++) {
9167                                         guint16 val = read16 (p);
9168                                         mono_array_set (arr, guint16, i, val);
9169                                         p += 2;
9170                                 }
9171                                 break;
9172                         case MONO_TYPE_R4:
9173                         case MONO_TYPE_U4:
9174                         case MONO_TYPE_I4:
9175                                 for (i = 0; i < alen; i++) {
9176                                         guint32 val = read32 (p);
9177                                         mono_array_set (arr, guint32, i, val);
9178                                         p += 4;
9179                                 }
9180                                 break;
9181                         case MONO_TYPE_R8:
9182                                 for (i = 0; i < alen; i++) {
9183                                         double val;
9184                                         readr8 (p, &val);
9185                                         mono_array_set (arr, double, i, val);
9186                                         p += 8;
9187                                 }
9188                                 break;
9189                         case MONO_TYPE_U8:
9190                         case MONO_TYPE_I8:
9191                                 for (i = 0; i < alen; i++) {
9192                                         guint64 val = read64 (p);
9193                                         mono_array_set (arr, guint64, i, val);
9194                                         p += 8;
9195                                 }
9196                                 break;
9197                         case MONO_TYPE_CLASS:
9198                         case MONO_TYPE_OBJECT:
9199                         case MONO_TYPE_STRING:
9200                         case MONO_TYPE_SZARRAY:
9201                                 for (i = 0; i < alen; i++) {
9202                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9203                                         if (!mono_error_ok (error))
9204                                                 return NULL;
9205                                         mono_array_setref (arr, i, item);
9206                                 }
9207                                 break;
9208                         default:
9209                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9210                 }
9211                 *end=p;
9212                 return arr;
9213         }
9214         default:
9215                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9216         }
9217         return NULL;
9218 }
9219
9220 static MonoObject*
9221 load_cattr_value_boxed (MonoDomain *domain, MonoImage *image, MonoType *t, const char* p, const char** end, MonoError *error)
9222 {
9223         mono_error_init (error);
9224
9225         gboolean is_ref = type_is_reference (t);
9226
9227         void *val = load_cattr_value (image, t, p, end, error);
9228         if (!is_ok (error)) {
9229                 if (is_ref)
9230                         g_free (val);
9231                 return NULL;
9232         }
9233
9234         if (is_ref)
9235                 return (MonoObject*)val;
9236
9237         MonoObject *boxed = mono_value_box_checked (domain, mono_class_from_mono_type (t), val, error);
9238         g_free (val);
9239         return boxed;
9240 }
9241
9242 static MonoObject*
9243 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9244 {
9245         static MonoMethod *ctor;
9246         MonoObject *retval;
9247         void *params [2], *unboxed;
9248
9249         mono_error_init (error);
9250
9251         if (!ctor)
9252                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9253         
9254         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9255         return_val_if_nok (error, NULL);
9256
9257         params [1] = val;
9258         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9259         return_val_if_nok (error, NULL);
9260         unboxed = mono_object_unbox (retval);
9261
9262         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9263         return_val_if_nok (error, NULL);
9264
9265         return retval;
9266 }
9267
9268 static MonoObject*
9269 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9270 {
9271         static MonoMethod *ctor;
9272         MonoObject *retval;
9273         void *unboxed, *params [2];
9274
9275         mono_error_init (error);
9276
9277         if (!ctor)
9278                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9279
9280         params [0] = minfo;
9281         params [1] = typedarg;
9282         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9283         return_val_if_nok (error, NULL);
9284
9285         unboxed = mono_object_unbox (retval);
9286
9287         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9288         return_val_if_nok (error, NULL);
9289
9290         return retval;
9291 }
9292
9293 static gboolean
9294 type_is_reference (MonoType *type)
9295 {
9296         switch (type->type) {
9297         case MONO_TYPE_BOOLEAN:
9298         case MONO_TYPE_CHAR:
9299         case MONO_TYPE_U:
9300         case MONO_TYPE_I:
9301         case MONO_TYPE_U1:
9302         case MONO_TYPE_I1:
9303         case MONO_TYPE_U2:
9304         case MONO_TYPE_I2:
9305         case MONO_TYPE_U4:
9306         case MONO_TYPE_I4:
9307         case MONO_TYPE_U8:
9308         case MONO_TYPE_I8:
9309         case MONO_TYPE_R8:
9310         case MONO_TYPE_R4:
9311         case MONO_TYPE_VALUETYPE:
9312                 return FALSE;
9313         default:
9314                 return TRUE;
9315         }
9316 }
9317
9318 static void
9319 free_param_data (MonoMethodSignature *sig, void **params) {
9320         int i;
9321         for (i = 0; i < sig->param_count; ++i) {
9322                 if (!type_is_reference (sig->params [i]))
9323                         g_free (params [i]);
9324         }
9325 }
9326
9327 /*
9328  * Find the field index in the metadata FieldDef table.
9329  */
9330 static guint32
9331 find_field_index (MonoClass *klass, MonoClassField *field) {
9332         int i;
9333
9334         for (i = 0; i < klass->field.count; ++i) {
9335                 if (field == &klass->fields [i])
9336                         return klass->field.first + 1 + i;
9337         }
9338         return 0;
9339 }
9340
9341 /*
9342  * Find the property index in the metadata Property table.
9343  */
9344 static guint32
9345 find_property_index (MonoClass *klass, MonoProperty *property) {
9346         int i;
9347
9348         for (i = 0; i < klass->ext->property.count; ++i) {
9349                 if (property == &klass->ext->properties [i])
9350                         return klass->ext->property.first + 1 + i;
9351         }
9352         return 0;
9353 }
9354
9355 /*
9356  * Find the event index in the metadata Event table.
9357  */
9358 static guint32
9359 find_event_index (MonoClass *klass, MonoEvent *event) {
9360         int i;
9361
9362         for (i = 0; i < klass->ext->event.count; ++i) {
9363                 if (event == &klass->ext->events [i])
9364                         return klass->ext->event.first + 1 + i;
9365         }
9366         return 0;
9367 }
9368
9369 static MonoObject*
9370 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9371 {
9372         const char *p = (const char*)data;
9373         const char *named;
9374         guint32 i, j, num_named;
9375         MonoObject *attr;
9376         void *params_buf [32];
9377         void **params = NULL;
9378         MonoMethodSignature *sig;
9379         MonoObject *exc = NULL;
9380
9381         mono_error_init (error);
9382
9383         mono_class_init (method->klass);
9384
9385         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9386                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9387                 return NULL;
9388         }
9389
9390         if (len == 0) {
9391                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9392                 if (!mono_error_ok (error)) return NULL;
9393
9394                 mono_runtime_invoke_checked (method, attr, NULL, error);
9395                 if (!mono_error_ok (error))
9396                         return NULL;
9397
9398                 return attr;
9399         }
9400
9401         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9402                 return NULL;
9403
9404         /*g_print ("got attr %s\n", method->klass->name);*/
9405
9406         sig = mono_method_signature (method);
9407         if (sig->param_count < 32) {
9408                 params = params_buf;
9409                 memset (params, 0, sizeof (void*) * sig->param_count);
9410         } else {
9411                 /* Allocate using GC so it gets GC tracking */
9412                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9413         }
9414
9415         /* skip prolog */
9416         p += 2;
9417         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9418                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9419                 if (!mono_error_ok (error))
9420                         goto fail;
9421         }
9422
9423         named = p;
9424         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9425         if (!mono_error_ok (error)) goto fail;
9426
9427         mono_runtime_try_invoke (method, attr, params, &exc, error);
9428         if (!mono_error_ok (error))
9429                 goto fail;
9430         if (exc)
9431                 goto fail;
9432
9433         num_named = read16 (named);
9434         named += 2;
9435         for (j = 0; j < num_named; j++) {
9436                 gint name_len;
9437                 char *name, named_type, data_type;
9438                 named_type = *named++;
9439                 data_type = *named++; /* type of data */
9440                 if (data_type == MONO_TYPE_SZARRAY)
9441                         data_type = *named++;
9442                 if (data_type == MONO_TYPE_ENUM) {
9443                         gint type_len;
9444                         char *type_name;
9445                         type_len = mono_metadata_decode_blob_size (named, &named);
9446                         type_name = (char *)g_malloc (type_len + 1);
9447                         memcpy (type_name, named, type_len);
9448                         type_name [type_len] = 0;
9449                         named += type_len;
9450                         /* FIXME: lookup the type and check type consistency */
9451                         g_free (type_name);
9452                 }
9453                 name_len = mono_metadata_decode_blob_size (named, &named);
9454                 name = (char *)g_malloc (name_len + 1);
9455                 memcpy (name, named, name_len);
9456                 name [name_len] = 0;
9457                 named += name_len;
9458                 if (named_type == 0x53) {
9459                         MonoClassField *field;
9460                         void *val;
9461
9462                         /* how this fail is a blackbox */
9463                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9464                         if (!field) {
9465                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9466                                 g_free (name);
9467                                 goto fail;
9468                         }
9469
9470                         val = load_cattr_value (image, field->type, named, &named, error);
9471                         if (!mono_error_ok (error)) {
9472                                 g_free (name);
9473                                 if (!type_is_reference (field->type))
9474                                         g_free (val);
9475                                 goto fail;
9476                         }
9477
9478                         mono_field_set_value (attr, field, val);
9479                         if (!type_is_reference (field->type))
9480                                 g_free (val);
9481                 } else if (named_type == 0x54) {
9482                         MonoProperty *prop;
9483                         void *pparams [1];
9484                         MonoType *prop_type;
9485
9486                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9487
9488                         if (!prop) {
9489                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9490                                 g_free (name);
9491                                 goto fail;
9492                         }
9493
9494                         if (!prop->set) {
9495                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9496                                 g_free (name);
9497                                 goto fail;
9498                         }
9499
9500                         /* can we have more that 1 arg in a custom attr named property? */
9501                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9502                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9503
9504                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9505                         if (!mono_error_ok (error)) {
9506                                 g_free (name);
9507                                 if (!type_is_reference (prop_type))
9508                                         g_free (pparams [0]);
9509                                 goto fail;
9510                         }
9511
9512
9513                         mono_property_set_value (prop, attr, pparams, NULL);
9514                         if (!type_is_reference (prop_type))
9515                                 g_free (pparams [0]);
9516                 }
9517                 g_free (name);
9518         }
9519
9520         free_param_data (method->signature, params);
9521         if (params != params_buf)
9522                 mono_gc_free_fixed (params);
9523
9524         return attr;
9525
9526 fail:
9527         free_param_data (method->signature, params);
9528         if (params != params_buf)
9529                 mono_gc_free_fixed (params);
9530         if (exc)
9531                 mono_raise_exception ((MonoException*)exc);
9532         return NULL;
9533 }
9534         
9535 /*
9536  * mono_reflection_create_custom_attr_data_args:
9537  *
9538  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9539  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9540  * NAMED_ARG_INFO will contain information about the named arguments.
9541  */
9542 void
9543 mono_reflection_create_custom_attr_data_args (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoArray **typed_args, MonoArray **named_args, CattrNamedArg **named_arg_info, MonoError *error)
9544 {
9545         MonoArray *typedargs, *namedargs;
9546         MonoClass *attrklass;
9547         MonoDomain *domain;
9548         const char *p = (const char*)data;
9549         const char *named;
9550         guint32 i, j, num_named;
9551         CattrNamedArg *arginfo = NULL;
9552
9553         *typed_args = NULL;
9554         *named_args = NULL;
9555         *named_arg_info = NULL;
9556
9557         mono_error_init (error);
9558
9559         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9560                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9561                 return;
9562         }
9563
9564         mono_class_init (method->klass);
9565         
9566         domain = mono_domain_get ();
9567
9568         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9569                 return;
9570
9571         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9572         
9573         /* skip prolog */
9574         p += 2;
9575         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9576                 MonoObject *obj;
9577
9578                 obj = load_cattr_value_boxed (domain, image, mono_method_signature (method)->params [i], p, &p, error);
9579                 return_if_nok (error);
9580                 mono_array_setref (typedargs, i, obj);
9581         }
9582
9583         named = p;
9584         num_named = read16 (named);
9585         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9586         named += 2;
9587         attrklass = method->klass;
9588
9589         arginfo = g_new0 (CattrNamedArg, num_named);
9590         *named_arg_info = arginfo;
9591
9592         for (j = 0; j < num_named; j++) {
9593                 gint name_len;
9594                 char *name, named_type, data_type;
9595                 named_type = *named++;
9596                 data_type = *named++; /* type of data */
9597                 if (data_type == MONO_TYPE_SZARRAY)
9598                         data_type = *named++;
9599                 if (data_type == MONO_TYPE_ENUM) {
9600                         gint type_len;
9601                         char *type_name;
9602                         type_len = mono_metadata_decode_blob_size (named, &named);
9603                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9604                                 goto fail;
9605
9606                         type_name = (char *)g_malloc (type_len + 1);
9607                         memcpy (type_name, named, type_len);
9608                         type_name [type_len] = 0;
9609                         named += type_len;
9610                         /* FIXME: lookup the type and check type consistency */
9611                         g_free (type_name);
9612                 }
9613                 name_len = mono_metadata_decode_blob_size (named, &named);
9614                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9615                         goto fail;
9616                 name = (char *)g_malloc (name_len + 1);
9617                 memcpy (name, named, name_len);
9618                 name [name_len] = 0;
9619                 named += name_len;
9620                 if (named_type == 0x53) {
9621                         MonoObject *obj;
9622                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9623
9624                         if (!field) {
9625                                 g_free (name);
9626                                 goto fail;
9627                         }
9628
9629                         arginfo [j].type = field->type;
9630                         arginfo [j].field = field;
9631
9632                         obj = load_cattr_value_boxed (domain, image, field->type, named, &named, error);
9633                         if (!is_ok (error)) {
9634                                 g_free (name);
9635                                 return;
9636                         }
9637                         mono_array_setref (namedargs, j, obj);
9638
9639                 } else if (named_type == 0x54) {
9640                         MonoObject *obj;
9641                         MonoType *prop_type;
9642                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9643
9644                         if (!prop || !prop->set) {
9645                                 g_free (name);
9646                                 goto fail;
9647                         }
9648
9649                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9650                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9651
9652                         arginfo [j].type = prop_type;
9653                         arginfo [j].prop = prop;
9654
9655                         obj = load_cattr_value_boxed (domain, image, prop_type, named, &named, error);
9656                         if (!is_ok (error)) {
9657                                 g_free (name);
9658                                 return;
9659                         }
9660                         mono_array_setref (namedargs, j, obj);
9661                 }
9662                 g_free (name);
9663         }
9664
9665         *typed_args = typedargs;
9666         *named_args = namedargs;
9667         return;
9668 fail:
9669         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9670         g_free (arginfo);
9671         *named_arg_info = NULL;
9672 }
9673
9674 void
9675 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9676 {
9677         MonoDomain *domain;
9678         MonoArray *typedargs, *namedargs;
9679         MonoImage *image;
9680         MonoMethod *method;
9681         CattrNamedArg *arginfo = NULL;
9682         MonoError error;
9683         int i;
9684
9685         mono_error_init (&error);
9686
9687         *ctor_args = NULL;
9688         *named_args = NULL;
9689
9690         if (len == 0)
9691                 return;
9692
9693         image = assembly->assembly->image;
9694         method = ref_method->method;
9695         domain = mono_object_domain (ref_method);
9696
9697         if (!mono_class_init (method->klass))
9698                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9699
9700         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9701         if (!mono_error_ok (&error))
9702                 goto leave;
9703
9704         if (mono_loader_get_last_error ()) {
9705                 mono_error_set_from_loader_error (&error);
9706                 goto leave;
9707         }
9708
9709         if (!typedargs || !namedargs)
9710                 goto leave;
9711
9712         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9713                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9714                 MonoObject *typedarg;
9715
9716                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9717                 if (!is_ok (&error))
9718                         goto leave;
9719                 mono_array_setref (typedargs, i, typedarg);
9720         }
9721
9722         for (i = 0; i < mono_array_length (namedargs); ++i) {
9723                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9724                 MonoObject *typedarg, *namedarg, *minfo;
9725
9726                 if (arginfo [i].prop) {
9727                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9728                         if (!minfo)
9729                                 goto leave;
9730                 } else {
9731                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9732                         if (!mono_error_ok (&error))
9733                                 goto leave;
9734                 }
9735
9736                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9737                 if (!is_ok (&error))
9738                         goto leave;
9739                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9740                 if (!is_ok (&error))
9741                         goto leave;
9742
9743                 mono_array_setref (namedargs, i, namedarg);
9744         }
9745
9746         *ctor_args = typedargs;
9747         *named_args = namedargs;
9748 leave:
9749         g_free (arginfo);
9750         mono_error_raise_exception (&error);
9751
9752 }
9753
9754 static MonoObject*
9755 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9756 {
9757         static MonoMethod *ctor;
9758
9759         MonoDomain *domain;
9760         MonoObject *attr;
9761         void *params [4];
9762
9763         mono_error_init (error);
9764
9765         g_assert (image->assembly);
9766
9767         if (!ctor)
9768                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9769
9770         domain = mono_domain_get ();
9771         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9772         return_val_if_nok (error, NULL);
9773         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9774         return_val_if_nok (error, NULL);
9775         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9776         return_val_if_nok (error, NULL);
9777         params [2] = (gpointer)&cattr->data;
9778         params [3] = &cattr->data_size;
9779
9780         mono_runtime_invoke_checked (ctor, attr, params, error);
9781         return_val_if_nok (error, NULL);
9782         return attr;
9783 }
9784
9785 static MonoArray*
9786 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9787 {
9788         MonoArray *result;
9789         MonoObject *attr;
9790         int i, n;
9791
9792         mono_error_init (error);
9793
9794         n = 0;
9795         for (i = 0; i < cinfo->num_attrs; ++i) {
9796                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9797                         n ++;
9798         }
9799
9800         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9801         n = 0;
9802         for (i = 0; i < cinfo->num_attrs; ++i) {
9803                 if (!cinfo->attrs [i].ctor) {
9804                         /* The cattr type is not finished yet */
9805                         /* We should include the type name but cinfo doesn't contain it */
9806                         mono_error_set_type_load_name (error, NULL, NULL, "");
9807                         return NULL;
9808                 }
9809                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9810                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9811                         if (!mono_error_ok (error))
9812                                 return result;
9813                         mono_array_setref (result, n, attr);
9814                         n ++;
9815                 }
9816         }
9817         return result;
9818 }
9819
9820 MonoArray*
9821 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9822 {
9823         MonoError error;
9824         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9825         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9826
9827         return result;
9828 }
9829
9830 static MonoArray*
9831 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9832 {
9833         MonoArray *result;
9834         MonoObject *attr;
9835         int i;
9836         
9837         mono_error_init (error);
9838         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9839         for (i = 0; i < cinfo->num_attrs; ++i) {
9840                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9841                 return_val_if_nok (error, NULL);
9842                 mono_array_setref (result, i, attr);
9843         }
9844         return result;
9845 }
9846
9847 /**
9848  * mono_custom_attrs_from_index:
9849  *
9850  * Returns: NULL if no attributes are found or if a loading error occurs.
9851  */
9852 MonoCustomAttrInfo*
9853 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9854 {
9855         MonoError error;
9856         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9857         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9858         return result;
9859 }
9860 /**
9861  * mono_custom_attrs_from_index_checked:
9862  *
9863  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9864  */
9865 MonoCustomAttrInfo*
9866 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9867 {
9868         guint32 mtoken, i, len;
9869         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9870         MonoTableInfo *ca;
9871         MonoCustomAttrInfo *ainfo;
9872         GList *tmp, *list = NULL;
9873         const char *data;
9874         MonoCustomAttrEntry* attr;
9875
9876         mono_error_init (error);
9877
9878         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9879
9880         i = mono_metadata_custom_attrs_from_index (image, idx);
9881         if (!i)
9882                 return NULL;
9883         i --;
9884         while (i < ca->rows) {
9885                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9886                         break;
9887                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9888                 ++i;
9889         }
9890         len = g_list_length (list);
9891         if (!len)
9892                 return NULL;
9893         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9894         ainfo->num_attrs = len;
9895         ainfo->image = image;
9896         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9897                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9898                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9899                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9900                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9901                         mtoken |= MONO_TOKEN_METHOD_DEF;
9902                         break;
9903                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9904                         mtoken |= MONO_TOKEN_MEMBER_REF;
9905                         break;
9906                 default:
9907                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9908                         break;
9909                 }
9910                 attr = &ainfo->attrs [i - 1];
9911                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9912                 if (!attr->ctor) {
9913                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9914                         g_list_free (list);
9915                         g_free (ainfo);
9916                         return NULL;
9917                 }
9918
9919                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9920                         /*FIXME raising an exception here doesn't make any sense*/
9921                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9922                         g_list_free (list);
9923                         g_free (ainfo);
9924                         return NULL;
9925                 }
9926                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9927                 attr->data_size = mono_metadata_decode_value (data, &data);
9928                 attr->data = (guchar*)data;
9929         }
9930         g_list_free (list);
9931
9932         return ainfo;
9933 }
9934
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_method (MonoMethod *method)
9937 {
9938         MonoError error;
9939         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9940         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941         return result;
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9946 {
9947         guint32 idx;
9948
9949         mono_error_init (error);
9950
9951         /*
9952          * An instantiated method has the same cattrs as the generic method definition.
9953          *
9954          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9955          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9956          */
9957         if (method->is_inflated)
9958                 method = ((MonoMethodInflated *) method)->declaring;
9959         
9960         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9961                 return lookup_custom_attr (method->klass->image, method);
9962
9963         if (!method->token)
9964                 /* Synthetic methods */
9965                 return NULL;
9966
9967         idx = mono_method_get_index (method);
9968         idx <<= MONO_CUSTOM_ATTR_BITS;
9969         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9970         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9971 }
9972
9973 MonoCustomAttrInfo*
9974 mono_custom_attrs_from_class (MonoClass *klass)
9975 {
9976         MonoError error;
9977         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9978         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9979         return result;
9980 }
9981
9982 MonoCustomAttrInfo*
9983 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9984 {
9985         guint32 idx;
9986
9987         mono_error_init (error);
9988
9989         if (klass->generic_class)
9990                 klass = klass->generic_class->container_class;
9991
9992         if (image_is_dynamic (klass->image))
9993                 return lookup_custom_attr (klass->image, klass);
9994
9995         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9996                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9997                 idx <<= MONO_CUSTOM_ATTR_BITS;
9998                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9999         } else {
10000                 idx = mono_metadata_token_index (klass->type_token);
10001                 idx <<= MONO_CUSTOM_ATTR_BITS;
10002                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
10003         }
10004         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10005 }
10006
10007 MonoCustomAttrInfo*
10008 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
10009 {
10010         MonoError error;
10011         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
10012         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10013         return result;
10014 }
10015
10016 MonoCustomAttrInfo*
10017 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
10018 {
10019         guint32 idx;
10020         
10021         mono_error_init (error);
10022
10023         if (image_is_dynamic (assembly->image))
10024                 return lookup_custom_attr (assembly->image, assembly);
10025         idx = 1; /* there is only one assembly */
10026         idx <<= MONO_CUSTOM_ATTR_BITS;
10027         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
10028         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
10029 }
10030
10031 static MonoCustomAttrInfo*
10032 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
10033 {
10034         guint32 idx;
10035         
10036         if (image_is_dynamic (image))
10037                 return lookup_custom_attr (image, image);
10038         idx = 1; /* there is only one module */
10039         idx <<= MONO_CUSTOM_ATTR_BITS;
10040         idx |= MONO_CUSTOM_ATTR_MODULE;
10041         return mono_custom_attrs_from_index_checked (image, idx, error);
10042 }
10043
10044 MonoCustomAttrInfo*
10045 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
10046 {
10047         MonoError error;
10048         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
10049         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10050         return result;
10051 }
10052
10053 MonoCustomAttrInfo*
10054 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
10055 {
10056         guint32 idx;
10057         
10058         if (image_is_dynamic (klass->image)) {
10059                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
10060                 return lookup_custom_attr (klass->image, property);
10061         }
10062         idx = find_property_index (klass, property);
10063         idx <<= MONO_CUSTOM_ATTR_BITS;
10064         idx |= MONO_CUSTOM_ATTR_PROPERTY;
10065         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10066 }
10067
10068 MonoCustomAttrInfo*
10069 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
10070 {
10071         MonoError error;
10072         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
10073         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10074         return result;
10075 }
10076
10077 MonoCustomAttrInfo*
10078 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
10079 {
10080         guint32 idx;
10081         
10082         if (image_is_dynamic (klass->image)) {
10083                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
10084                 return lookup_custom_attr (klass->image, event);
10085         }
10086         idx = find_event_index (klass, event);
10087         idx <<= MONO_CUSTOM_ATTR_BITS;
10088         idx |= MONO_CUSTOM_ATTR_EVENT;
10089         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10090 }
10091
10092 MonoCustomAttrInfo*
10093 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
10094 {
10095         MonoError error;
10096         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
10097         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10098         return result;
10099 }
10100
10101 MonoCustomAttrInfo*
10102 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
10103 {
10104         guint32 idx;
10105         mono_error_init (error);
10106
10107         if (image_is_dynamic (klass->image)) {
10108                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
10109                 return lookup_custom_attr (klass->image, field);
10110         }
10111         idx = find_field_index (klass, field);
10112         idx <<= MONO_CUSTOM_ATTR_BITS;
10113         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
10114         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
10115 }
10116
10117 /**
10118  * mono_custom_attrs_from_param:
10119  * @method: handle to the method that we want to retrieve custom parameter information from
10120  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10121  *
10122  * The result must be released with mono_custom_attrs_free().
10123  *
10124  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10125  */
10126 MonoCustomAttrInfo*
10127 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10128 {
10129         MonoError error;
10130         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10131         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10132         return result;
10133 }
10134
10135 /**
10136  * mono_custom_attrs_from_param_checked:
10137  * @method: handle to the method that we want to retrieve custom parameter information from
10138  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10139  * @error: set on error
10140  *
10141  * The result must be released with mono_custom_attrs_free().
10142  *
10143  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10144  */
10145 MonoCustomAttrInfo*
10146 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10147 {
10148         MonoTableInfo *ca;
10149         guint32 i, idx, method_index;
10150         guint32 param_list, param_last, param_pos, found;
10151         MonoImage *image;
10152         MonoReflectionMethodAux *aux;
10153
10154         mono_error_init (error);
10155
10156         /*
10157          * An instantiated method has the same cattrs as the generic method definition.
10158          *
10159          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10160          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10161          */
10162         if (method->is_inflated)
10163                 method = ((MonoMethodInflated *) method)->declaring;
10164
10165         if (image_is_dynamic (method->klass->image)) {
10166                 MonoCustomAttrInfo *res, *ainfo;
10167                 int size;
10168
10169                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10170                 if (!aux || !aux->param_cattr)
10171                         return NULL;
10172
10173                 /* Need to copy since it will be freed later */
10174                 ainfo = aux->param_cattr [param];
10175                 if (!ainfo)
10176                         return NULL;
10177                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10178                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10179                 memcpy (res, ainfo, size);
10180                 return res;
10181         }
10182
10183         image = method->klass->image;
10184         method_index = mono_method_get_index (method);
10185         if (!method_index)
10186                 return NULL;
10187         ca = &image->tables [MONO_TABLE_METHOD];
10188
10189         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10190         if (method_index == ca->rows) {
10191                 ca = &image->tables [MONO_TABLE_PARAM];
10192                 param_last = ca->rows + 1;
10193         } else {
10194                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10195                 ca = &image->tables [MONO_TABLE_PARAM];
10196         }
10197         found = FALSE;
10198         for (i = param_list; i < param_last; ++i) {
10199                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10200                 if (param_pos == param) {
10201                         found = TRUE;
10202                         break;
10203                 }
10204         }
10205         if (!found)
10206                 return NULL;
10207         idx = i;
10208         idx <<= MONO_CUSTOM_ATTR_BITS;
10209         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10210         return mono_custom_attrs_from_index_checked (image, idx, error);
10211 }
10212
10213 gboolean
10214 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10215 {
10216         int i;
10217         MonoClass *klass;
10218         for (i = 0; i < ainfo->num_attrs; ++i) {
10219                 klass = ainfo->attrs [i].ctor->klass;
10220                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10221                         return TRUE;
10222         }
10223         return FALSE;
10224 }
10225
10226 MonoObject*
10227 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10228 {
10229         MonoError error;
10230         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10231         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10232         return res;
10233 }
10234
10235 MonoObject*
10236 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10237 {
10238         int i, attr_index;
10239         MonoClass *klass;
10240         MonoArray *attrs;
10241
10242         mono_error_init (error);
10243
10244         attr_index = -1;
10245         for (i = 0; i < ainfo->num_attrs; ++i) {
10246                 klass = ainfo->attrs [i].ctor->klass;
10247                 if (mono_class_has_parent (klass, attr_klass)) {
10248                         attr_index = i;
10249                         break;
10250                 }
10251         }
10252         if (attr_index == -1)
10253                 return NULL;
10254
10255         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10256         if (!mono_error_ok (error))
10257                 return NULL;
10258         return mono_array_get (attrs, MonoObject*, attr_index);
10259 }
10260
10261 /*
10262  * mono_reflection_get_custom_attrs_info:
10263  * @obj: a reflection object handle
10264  *
10265  * Return the custom attribute info for attributes defined for the
10266  * reflection handle @obj. The objects.
10267  *
10268  * FIXME this function leaks like a sieve for SRE objects.
10269  */
10270 MonoCustomAttrInfo*
10271 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10272 {
10273         MonoError error;
10274         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10275         mono_error_assert_ok (&error);
10276         return result;
10277 }
10278
10279 /**
10280  * mono_reflection_get_custom_attrs_info_checked:
10281  * @obj: a reflection object handle
10282  * @error: set on error
10283  *
10284  * Return the custom attribute info for attributes defined for the
10285  * reflection handle @obj. The objects.
10286  *
10287  * On failure returns NULL and sets @error.
10288  *
10289  * FIXME this function leaks like a sieve for SRE objects.
10290  */
10291 MonoCustomAttrInfo*
10292 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10293 {
10294         MonoClass *klass;
10295         MonoCustomAttrInfo *cinfo = NULL;
10296         
10297         mono_error_init (error);
10298
10299         klass = obj->vtable->klass;
10300         if (klass == mono_defaults.monotype_class) {
10301                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10302                 return_val_if_nok (error, NULL);
10303                 klass = mono_class_from_mono_type (type);
10304                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10305                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10306                 return_val_if_nok (error, NULL);
10307         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10308                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10309                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10310                 return_val_if_nok (error, NULL);
10311         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10312                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10313                 cinfo = mono_custom_attrs_from_module (module->image, error);
10314                 return_val_if_nok (error, NULL);
10315         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10316                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10317                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10318                 return_val_if_nok (error, NULL);
10319         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10320                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10321                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10322                 return_val_if_nok (error, NULL);
10323         } else if (strcmp ("MonoField", klass->name) == 0) {
10324                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10325                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10326                 return_val_if_nok (error, NULL);
10327         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10328                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10329                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10330                 return_val_if_nok (error, NULL);
10331         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10332                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10333                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10334                 return_val_if_nok (error, NULL);
10335         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10336                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10337                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10338                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10339                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10340                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10341                         return_val_if_nok (error, NULL);
10342                 } else if (is_sr_mono_property (member_class)) {
10343                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10344                         MonoMethod *method;
10345                         if (!(method = prop->property->get))
10346                                 method = prop->property->set;
10347                         g_assert (method);
10348
10349                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10350                         return_val_if_nok (error, NULL);
10351                 } 
10352 #ifndef DISABLE_REFLECTION_EMIT
10353                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10354                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10355                         return_val_if_nok (error, NULL);
10356                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10357                         return_val_if_nok (error, NULL);
10358                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10359                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10360                         MonoMethod *method = NULL;
10361                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10362                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10363                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10364                                 method = ((MonoReflectionMethod *)c->cb)->method;
10365                         else
10366                                 g_error ("mono_reflection_get_custom_attrs_info:: can't handle a CTBI with base_method of type %s", mono_type_get_full_name (member_class));
10367
10368                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10369                         return_val_if_nok (error, NULL);
10370                 } 
10371 #endif
10372                 else {
10373                         char *type_name = mono_type_get_full_name (member_class);
10374                         mono_error_set_not_supported (error,
10375                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10376                                                       type_name);
10377                         g_free (type_name);
10378                         return NULL;
10379                 }
10380         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10381                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10382                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10383         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10384                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10385                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10386         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10387                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10388                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10389         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10390                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10391                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10392         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10393                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10394                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10395         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10396                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10397                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10398         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10399                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10400                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10401                 return_val_if_nok (error, NULL);
10402         } else { /* handle other types here... */
10403                 g_error ("get custom attrs not yet supported for %s", klass->name);
10404         }
10405
10406         return cinfo;
10407 }
10408
10409 /*
10410  * mono_reflection_get_custom_attrs_by_type:
10411  * @obj: a reflection object handle
10412  *
10413  * Return an array with all the custom attributes defined of the
10414  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10415  * of that type are returned. The objects are fully build. Return NULL if a loading error
10416  * occurs.
10417  */
10418 MonoArray*
10419 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10420 {
10421         MonoArray *result;
10422         MonoCustomAttrInfo *cinfo;
10423
10424         mono_error_init (error);
10425
10426         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10427         return_val_if_nok (error, NULL);
10428         if (cinfo) {
10429                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10430                 if (!result)
10431                         return NULL;
10432                 if (!cinfo->cached)
10433                         mono_custom_attrs_free (cinfo);
10434         } else {
10435                 mono_loader_assert_no_error ();
10436                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10437         }
10438
10439         return result;
10440 }
10441
10442 /*
10443  * mono_reflection_get_custom_attrs:
10444  * @obj: a reflection object handle
10445  *
10446  * Return an array with all the custom attributes defined of the
10447  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10448  * occurs.
10449  */
10450 MonoArray*
10451 mono_reflection_get_custom_attrs (MonoObject *obj)
10452 {
10453         MonoError error;
10454
10455         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10456 }
10457
10458 /*
10459  * mono_reflection_get_custom_attrs_data:
10460  * @obj: a reflection obj handle
10461  *
10462  * Returns an array of System.Reflection.CustomAttributeData,
10463  * which include information about attributes reflected on
10464  * types loaded using the Reflection Only methods
10465  */
10466 MonoArray*
10467 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10468 {
10469         MonoError error;
10470         MonoArray* result;
10471         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10472         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10473         return result;
10474 }
10475
10476 /*
10477  * mono_reflection_get_custom_attrs_data_checked:
10478  * @obj: a reflection obj handle
10479  * @error: set on error
10480  *
10481  * Returns an array of System.Reflection.CustomAttributeData,
10482  * which include information about attributes reflected on
10483  * types loaded using the Reflection Only methods
10484  */
10485 MonoArray*
10486 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10487 {
10488         MonoArray *result;
10489         MonoCustomAttrInfo *cinfo;
10490
10491         mono_error_init (error);
10492
10493         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10494         return_val_if_nok (error, NULL);
10495         if (cinfo) {
10496                 result = mono_custom_attrs_data_construct (cinfo, error);
10497                 return_val_if_nok (error, NULL);
10498                 if (!cinfo->cached)
10499                         mono_custom_attrs_free (cinfo);
10500         } else
10501                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10502
10503         if (mono_loader_get_last_error ())
10504                 mono_error_set_from_loader_error (error);
10505
10506         return result;
10507 }
10508
10509 static MonoReflectionType*
10510 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10511 {
10512         static MonoMethod *method_get_underlying_system_type = NULL;
10513         MonoReflectionType *rt;
10514         MonoMethod *usertype_method;
10515
10516         mono_error_init (error);
10517
10518         if (!method_get_underlying_system_type)
10519                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10520
10521         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10522
10523         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10524
10525         return rt;
10526 }
10527
10528
10529 static gboolean
10530 is_corlib_type (MonoClass *klass)
10531 {
10532         return klass->image == mono_defaults.corlib;
10533 }
10534
10535 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10536         static MonoClass *cached_class; \
10537         if (cached_class) \
10538                 return cached_class == _class; \
10539         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10540                 cached_class = _class; \
10541                 return TRUE; \
10542         } \
10543         return FALSE; \
10544 } while (0) \
10545
10546
10547 #ifndef DISABLE_REFLECTION_EMIT
10548 static gboolean
10549 is_sre_array (MonoClass *klass)
10550 {
10551         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10552 }
10553
10554 static gboolean
10555 is_sre_byref (MonoClass *klass)
10556 {
10557         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10558 }
10559
10560 static gboolean
10561 is_sre_pointer (MonoClass *klass)
10562 {
10563         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10564 }
10565
10566 static gboolean
10567 is_sre_generic_instance (MonoClass *klass)
10568 {
10569         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10570 }
10571
10572 static gboolean
10573 is_sre_type_builder (MonoClass *klass)
10574 {
10575         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10576 }
10577
10578 static gboolean
10579 is_sre_method_builder (MonoClass *klass)
10580 {
10581         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10582 }
10583
10584 static gboolean
10585 is_sre_ctor_builder (MonoClass *klass)
10586 {
10587         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10588 }
10589
10590 static gboolean
10591 is_sre_field_builder (MonoClass *klass)
10592 {
10593         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10594 }
10595
10596 static gboolean
10597 is_sre_method_on_tb_inst (MonoClass *klass)
10598 {
10599         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10600 }
10601
10602 static gboolean
10603 is_sre_ctor_on_tb_inst (MonoClass *klass)
10604 {
10605         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10606 }
10607
10608 MonoType*
10609 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10610 {
10611         MonoClass *klass;
10612         mono_error_init (error);
10613
10614         if (!ref)
10615                 return NULL;
10616         if (ref->type)
10617                 return ref->type;
10618
10619         if (is_usertype (ref)) {
10620                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10621                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10622                         return NULL;
10623                 if (ref->type)
10624                         return ref->type;
10625         }
10626
10627         klass = mono_object_class (ref);
10628
10629         if (is_sre_array (klass)) {
10630                 MonoType *res;
10631                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10632                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10633                 return_val_if_nok (error, NULL);
10634                 g_assert (base);
10635                 if (sre_array->rank == 0) //single dimentional array
10636                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10637                 else
10638                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10639                 sre_array->type.type = res;
10640                 return res;
10641         } else if (is_sre_byref (klass)) {
10642                 MonoType *res;
10643                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10644                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10645                 return_val_if_nok (error, NULL);
10646                 g_assert (base);
10647                 res = &mono_class_from_mono_type (base)->this_arg;
10648                 sre_byref->type.type = res;
10649                 return res;
10650         } else if (is_sre_pointer (klass)) {
10651                 MonoType *res;
10652                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10653                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10654                 return_val_if_nok (error, NULL);
10655                 g_assert (base);
10656                 res = &mono_ptr_class_get (base)->byval_arg;
10657                 sre_pointer->type.type = res;
10658                 return res;
10659         } else if (is_sre_generic_instance (klass)) {
10660                 MonoType *res, **types;
10661                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10662                 int i, count;
10663
10664                 count = mono_array_length (gclass->type_arguments);
10665                 types = g_new0 (MonoType*, count);
10666                 for (i = 0; i < count; ++i) {
10667                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10668                         types [i] = mono_reflection_type_get_handle (t, error);
10669                         if (!types[i] || !is_ok (error)) {
10670                                 g_free (types);
10671                                 return NULL;
10672                         }
10673                 }
10674
10675                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types, error);
10676                 g_free (types);
10677                 g_assert (res);
10678                 gclass->type.type = res;
10679                 return res;
10680         }
10681
10682         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10683         return NULL;
10684 }
10685
10686 void
10687 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10688 {
10689         MonoError error;
10690         mono_reflection_type_get_handle (type, &error);
10691         mono_error_set_pending_exception (&error);
10692 }
10693
10694 static gboolean
10695 reflection_register_with_runtime (MonoReflectionType *type, MonoError *error)
10696 {
10697         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10698         MonoClass *klass;
10699
10700         mono_error_init (error);
10701
10702         MonoType *res = mono_reflection_type_get_handle (type, error);
10703
10704         if (!res && is_ok (error)) {
10705                 mono_error_set_argument (error, NULL, "Invalid generic instantiation, one or more arguments are not proper user types");
10706         }
10707         return_val_if_nok (error, FALSE);
10708
10709         klass = mono_class_from_mono_type (res);
10710
10711         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10712         mono_domain_lock (domain);
10713
10714         if (!image_is_dynamic (klass->image)) {
10715                 mono_class_setup_supertypes (klass);
10716         } else {
10717                 if (!domain->type_hash)
10718                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10719                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10720                 mono_g_hash_table_insert (domain->type_hash, res, type);
10721         }
10722         mono_domain_unlock (domain);
10723         mono_loader_unlock ();
10724
10725         return TRUE;
10726 }
10727
10728 void
10729 mono_reflection_register_with_runtime (MonoReflectionType *type)
10730 {
10731         MonoError error;
10732         (void) reflection_register_with_runtime (type, &error);
10733         mono_error_set_pending_exception (&error);
10734 }
10735
10736 /**
10737  * LOCKING: Assumes the loader lock is held.
10738  */
10739 static MonoMethodSignature*
10740 parameters_to_signature (MonoImage *image, MonoArray *parameters, MonoError *error) {
10741         MonoMethodSignature *sig;
10742         int count, i;
10743
10744         mono_error_init (error);
10745
10746         count = parameters? mono_array_length (parameters): 0;
10747
10748         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10749         sig->param_count = count;
10750         sig->sentinelpos = -1; /* FIXME */
10751         for (i = 0; i < count; ++i) {
10752                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
10753                 if (!is_ok (error)) {
10754                         image_g_free (image, sig);
10755                         return NULL;
10756                 }
10757         }
10758         return sig;
10759 }
10760
10761 /**
10762  * LOCKING: Assumes the loader lock is held.
10763  */
10764 static MonoMethodSignature*
10765 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor, MonoError *error) {
10766         MonoMethodSignature *sig;
10767
10768         mono_error_init (error);
10769
10770         sig = parameters_to_signature (image, ctor->parameters, error);
10771         return_val_if_nok (error, NULL);
10772         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10773         sig->ret = &mono_defaults.void_class->byval_arg;
10774         return sig;
10775 }
10776
10777 /**
10778  * LOCKING: Assumes the loader lock is held.
10779  */
10780 static MonoMethodSignature*
10781 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method, MonoError *error) {
10782         MonoMethodSignature *sig;
10783
10784         mono_error_init (error);
10785
10786         sig = parameters_to_signature (image, method->parameters, error);
10787         return_val_if_nok (error, NULL);
10788         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10789         if (method->rtype) {
10790                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, error);
10791                 if (!is_ok (error)) {
10792                         image_g_free (image, sig);
10793                         return NULL;
10794                 }
10795         } else {
10796                 sig->ret = &mono_defaults.void_class->byval_arg;
10797         }
10798         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10799         return sig;
10800 }
10801
10802 static MonoMethodSignature*
10803 dynamic_method_to_signature (MonoReflectionDynamicMethod *method, MonoError *error) {
10804         MonoMethodSignature *sig;
10805
10806         mono_error_init (error);
10807
10808         sig = parameters_to_signature (NULL, method->parameters, error);
10809         return_val_if_nok (error, NULL);
10810         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10811         if (method->rtype) {
10812                 sig->ret = mono_reflection_type_get_handle (method->rtype, error);
10813                 if (!is_ok (error)) {
10814                         g_free (sig);
10815                         return NULL;
10816                 }
10817         } else {
10818                 sig->ret = &mono_defaults.void_class->byval_arg;
10819         }
10820         sig->generic_param_count = 0;
10821         return sig;
10822 }
10823
10824 static void
10825 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
10826 {
10827         mono_error_init (error);
10828         MonoClass *klass = mono_object_class (prop);
10829         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10830                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10831                 *name = mono_string_to_utf8 (pb->name);
10832                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
10833         } else {
10834                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10835                 *name = g_strdup (p->property->name);
10836                 if (p->property->get)
10837                         *type = mono_method_signature (p->property->get)->ret;
10838                 else
10839                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10840         }
10841 }
10842
10843 static void
10844 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
10845 {
10846         mono_error_init (error);
10847         MonoClass *klass = mono_object_class (field);
10848         if (strcmp (klass->name, "FieldBuilder") == 0) {
10849                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10850                 *name = mono_string_to_utf8 (fb->name);
10851                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
10852         } else {
10853                 MonoReflectionField *f = (MonoReflectionField *)field;
10854                 *name = g_strdup (mono_field_get_name (f->field));
10855                 *type = f->field->type;
10856         }
10857 }
10858
10859 #else /* DISABLE_REFLECTION_EMIT */
10860
10861 void
10862 mono_reflection_register_with_runtime (MonoReflectionType *type)
10863 {
10864         /* This is empty */
10865 }
10866
10867 static gboolean
10868 is_sre_type_builder (MonoClass *klass)
10869 {
10870         return FALSE;
10871 }
10872
10873 static gboolean
10874 is_sre_generic_instance (MonoClass *klass)
10875 {
10876         return FALSE;
10877 }
10878
10879 static void
10880 init_type_builder_generics (MonoObject *type)
10881 {
10882 }
10883
10884 #endif /* !DISABLE_REFLECTION_EMIT */
10885
10886
10887 static gboolean
10888 is_sr_mono_field (MonoClass *klass)
10889 {
10890         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10891 }
10892
10893 static gboolean
10894 is_sr_mono_property (MonoClass *klass)
10895 {
10896         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10897 }
10898
10899 static gboolean
10900 is_sr_mono_method (MonoClass *klass)
10901 {
10902         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10903 }
10904
10905 static gboolean
10906 is_sr_mono_cmethod (MonoClass *klass)
10907 {
10908         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10909 }
10910
10911 static gboolean
10912 is_sr_mono_generic_method (MonoClass *klass)
10913 {
10914         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10915 }
10916
10917 static gboolean
10918 is_sr_mono_generic_cmethod (MonoClass *klass)
10919 {
10920         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10921 }
10922
10923 gboolean
10924 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10925 {
10926         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10927 }
10928
10929 static gboolean
10930 is_usertype (MonoReflectionType *ref)
10931 {
10932         MonoClass *klass = mono_object_class (ref);
10933         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10934 }
10935
10936 static MonoReflectionType*
10937 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10938 {
10939         mono_error_init (error);
10940         if (!type || type->type)
10941                 return type;
10942
10943         if (is_usertype (type)) {
10944                 type = mono_reflection_type_get_underlying_system_type (type, error);
10945                 return_val_if_nok (error, NULL);
10946                 if (is_usertype (type)) {
10947                         mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported22");
10948                         return NULL;
10949                 }
10950         }
10951
10952         return type;
10953 }
10954 /**
10955  * encode_cattr_value:
10956  * Encode a value in a custom attribute stream of bytes.
10957  * The value to encode is either supplied as an object in argument val
10958  * (valuetypes are boxed), or as a pointer to the data in the
10959  * argument argval.
10960  * @type represents the type of the value
10961  * @buffer is the start of the buffer
10962  * @p the current position in the buffer
10963  * @buflen contains the size of the buffer and is used to return the new buffer size
10964  * if this needs to be realloced.
10965  * @retbuffer and @retp return the start and the position of the buffer
10966  * @error set on error.
10967  */
10968 static void
10969 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
10970 {
10971         MonoTypeEnum simple_type;
10972         
10973         mono_error_init (error);
10974         if ((p-buffer) + 10 >= *buflen) {
10975                 char *newbuf;
10976                 *buflen *= 2;
10977                 newbuf = (char *)g_realloc (buffer, *buflen);
10978                 p = newbuf + (p-buffer);
10979                 buffer = newbuf;
10980         }
10981         if (!argval)
10982                 argval = ((char*)arg + sizeof (MonoObject));
10983         simple_type = type->type;
10984 handle_enum:
10985         switch (simple_type) {
10986         case MONO_TYPE_BOOLEAN:
10987         case MONO_TYPE_U1:
10988         case MONO_TYPE_I1:
10989                 *p++ = *argval;
10990                 break;
10991         case MONO_TYPE_CHAR:
10992         case MONO_TYPE_U2:
10993         case MONO_TYPE_I2:
10994                 swap_with_size (p, argval, 2, 1);
10995                 p += 2;
10996                 break;
10997         case MONO_TYPE_U4:
10998         case MONO_TYPE_I4:
10999         case MONO_TYPE_R4:
11000                 swap_with_size (p, argval, 4, 1);
11001                 p += 4;
11002                 break;
11003         case MONO_TYPE_R8:
11004                 swap_with_size (p, argval, 8, 1);
11005                 p += 8;
11006                 break;
11007         case MONO_TYPE_U8:
11008         case MONO_TYPE_I8:
11009                 swap_with_size (p, argval, 8, 1);
11010                 p += 8;
11011                 break;
11012         case MONO_TYPE_VALUETYPE:
11013                 if (type->data.klass->enumtype) {
11014                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
11015                         goto handle_enum;
11016                 } else {
11017                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
11018                 }
11019                 break;
11020         case MONO_TYPE_STRING: {
11021                 char *str;
11022                 guint32 slen;
11023                 if (!arg) {
11024                         *p++ = 0xFF;
11025                         break;
11026                 }
11027                 str = mono_string_to_utf8 ((MonoString*)arg);
11028                 slen = strlen (str);
11029                 if ((p-buffer) + 10 + slen >= *buflen) {
11030                         char *newbuf;
11031                         *buflen *= 2;
11032                         *buflen += slen;
11033                         newbuf = (char *)g_realloc (buffer, *buflen);
11034                         p = newbuf + (p-buffer);
11035                         buffer = newbuf;
11036                 }
11037                 mono_metadata_encode_value (slen, p, &p);
11038                 memcpy (p, str, slen);
11039                 p += slen;
11040                 g_free (str);
11041                 break;
11042         }
11043         case MONO_TYPE_CLASS: {
11044                 char *str;
11045                 guint32 slen;
11046                 MonoType *arg_type;
11047                 if (!arg) {
11048                         *p++ = 0xFF;
11049                         break;
11050                 }
11051 handle_type:
11052                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
11053                 return_if_nok (error);
11054
11055                 str = type_get_qualified_name (arg_type, NULL);
11056                 slen = strlen (str);
11057                 if ((p-buffer) + 10 + slen >= *buflen) {
11058                         char *newbuf;
11059                         *buflen *= 2;
11060                         *buflen += slen;
11061                         newbuf = (char *)g_realloc (buffer, *buflen);
11062                         p = newbuf + (p-buffer);
11063                         buffer = newbuf;
11064                 }
11065                 mono_metadata_encode_value (slen, p, &p);
11066                 memcpy (p, str, slen);
11067                 p += slen;
11068                 g_free (str);
11069                 break;
11070         }
11071         case MONO_TYPE_SZARRAY: {
11072                 int len, i;
11073                 MonoClass *eclass, *arg_eclass;
11074
11075                 if (!arg) {
11076                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
11077                         break;
11078                 }
11079                 len = mono_array_length ((MonoArray*)arg);
11080                 *p++ = len & 0xff;
11081                 *p++ = (len >> 8) & 0xff;
11082                 *p++ = (len >> 16) & 0xff;
11083                 *p++ = (len >> 24) & 0xff;
11084                 *retp = p;
11085                 *retbuffer = buffer;
11086                 eclass = type->data.klass;
11087                 arg_eclass = mono_object_class (arg)->element_class;
11088
11089                 if (!eclass) {
11090                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
11091                         eclass = mono_defaults.object_class;
11092                 }
11093                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
11094                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11095                         int elsize = mono_class_array_element_size (arg_eclass);
11096                         for (i = 0; i < len; ++i) {
11097                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
11098                                 return_if_nok (error);
11099                                 elptr += elsize;
11100                         }
11101                 } else if (eclass->valuetype && arg_eclass->valuetype) {
11102                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
11103                         int elsize = mono_class_array_element_size (eclass);
11104                         for (i = 0; i < len; ++i) {
11105                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
11106                                 return_if_nok (error);
11107                                 elptr += elsize;
11108                         }
11109                 } else {
11110                         for (i = 0; i < len; ++i) {
11111                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
11112                                 return_if_nok (error);
11113                         }
11114                 }
11115                 break;
11116         }
11117         case MONO_TYPE_OBJECT: {
11118                 MonoClass *klass;
11119                 char *str;
11120                 guint32 slen;
11121
11122                 /*
11123                  * The parameter type is 'object' but the type of the actual
11124                  * argument is not. So we have to add type information to the blob
11125                  * too. This is completely undocumented in the spec.
11126                  */
11127
11128                 if (arg == NULL) {
11129                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
11130                         *p++ = 0xFF;
11131                         break;
11132                 }
11133                 
11134                 klass = mono_object_class (arg);
11135
11136                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
11137                         *p++ = 0x50;
11138                         goto handle_type;
11139                 } else if (klass->enumtype) {
11140                         *p++ = 0x55;
11141                 } else if (klass == mono_defaults.string_class) {
11142                         simple_type = MONO_TYPE_STRING;
11143                         *p++ = 0x0E;
11144                         goto handle_enum;
11145                 } else if (klass->rank == 1) {
11146                         *p++ = 0x1D;
11147                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
11148                                 /* See Partition II, Appendix B3 */
11149                                 *p++ = 0x51;
11150                         else
11151                                 *p++ = klass->element_class->byval_arg.type;
11152                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
11153                         return_if_nok (error);
11154                         break;
11155                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11156                         *p++ = simple_type = klass->byval_arg.type;
11157                         goto handle_enum;
11158                 } else {
11159                         g_error ("unhandled type in custom attr");
11160                 }
11161                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11162                 slen = strlen (str);
11163                 if ((p-buffer) + 10 + slen >= *buflen) {
11164                         char *newbuf;
11165                         *buflen *= 2;
11166                         *buflen += slen;
11167                         newbuf = (char *)g_realloc (buffer, *buflen);
11168                         p = newbuf + (p-buffer);
11169                         buffer = newbuf;
11170                 }
11171                 mono_metadata_encode_value (slen, p, &p);
11172                 memcpy (p, str, slen);
11173                 p += slen;
11174                 g_free (str);
11175                 simple_type = mono_class_enum_basetype (klass)->type;
11176                 goto handle_enum;
11177         }
11178         default:
11179                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11180         }
11181         *retp = p;
11182         *retbuffer = buffer;
11183 }
11184
11185 static void
11186 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11187 {
11188         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11189                 char *str = type_get_qualified_name (type, NULL);
11190                 int slen = strlen (str);
11191
11192                 *p++ = 0x55;
11193                 /*
11194                  * This seems to be optional...
11195                  * *p++ = 0x80;
11196                  */
11197                 mono_metadata_encode_value (slen, p, &p);
11198                 memcpy (p, str, slen);
11199                 p += slen;
11200                 g_free (str);
11201         } else if (type->type == MONO_TYPE_OBJECT) {
11202                 *p++ = 0x51;
11203         } else if (type->type == MONO_TYPE_CLASS) {
11204                 /* it should be a type: encode_cattr_value () has the check */
11205                 *p++ = 0x50;
11206         } else {
11207                 mono_metadata_encode_value (type->type, p, &p);
11208                 if (type->type == MONO_TYPE_SZARRAY)
11209                         /* See the examples in Partition VI, Annex B */
11210                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11211         }
11212
11213         *retp = p;
11214 }
11215
11216 #ifndef DISABLE_REFLECTION_EMIT
11217 static void
11218 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
11219 {
11220         int len;
11221
11222         mono_error_init (error);
11223
11224         /* Preallocate a large enough buffer */
11225         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11226                 char *str = type_get_qualified_name (type, NULL);
11227                 len = strlen (str);
11228                 g_free (str);
11229         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11230                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11231                 len = strlen (str);
11232                 g_free (str);
11233         } else {
11234                 len = 0;
11235         }
11236         len += strlen (name);
11237
11238         if ((p-buffer) + 20 + len >= *buflen) {
11239                 char *newbuf;
11240                 *buflen *= 2;
11241                 *buflen += len;
11242                 newbuf = (char *)g_realloc (buffer, *buflen);
11243                 p = newbuf + (p-buffer);
11244                 buffer = newbuf;
11245         }
11246
11247         encode_field_or_prop_type (type, p, &p);
11248
11249         len = strlen (name);
11250         mono_metadata_encode_value (len, p, &p);
11251         memcpy (p, name, len);
11252         p += len;
11253         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
11254         return_if_nok (error);
11255         *retp = p;
11256         *retbuffer = buffer;
11257 }
11258
11259 /**
11260  * mono_reflection_get_custom_attrs_blob:
11261  * @ctor: custom attribute constructor
11262  * @ctorArgs: arguments o the constructor
11263  * @properties:
11264  * @propValues:
11265  * @fields:
11266  * @fieldValues:
11267  * 
11268  * Creates the blob of data that needs to be saved in the metadata and that represents
11269  * the custom attributed described by @ctor, @ctorArgs etc.
11270  * Returns: a Byte array representing the blob of data.
11271  */
11272 MonoArray*
11273 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11274 {
11275         MonoError error;
11276         MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
11277         mono_error_cleanup (&error); /* FIXME better API that doesn't swallow the error */
11278         return result;
11279 }
11280
11281 /**
11282  * mono_reflection_get_custom_attrs_blob_checked:
11283  * @ctor: custom attribute constructor
11284  * @ctorArgs: arguments o the constructor
11285  * @properties:
11286  * @propValues:
11287  * @fields:
11288  * @fieldValues:
11289  * @error: set on error
11290  * 
11291  * Creates the blob of data that needs to be saved in the metadata and that represents
11292  * the custom attributed described by @ctor, @ctorArgs etc.
11293  * Returns: a Byte array representing the blob of data.  On failure returns NULL and sets @error.
11294  */
11295 MonoArray*
11296 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error) 
11297 {
11298         MonoArray *result = NULL;
11299         MonoMethodSignature *sig;
11300         MonoObject *arg;
11301         char *buffer, *p;
11302         guint32 buflen, i;
11303
11304         mono_error_init (error);
11305
11306         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11307                 /* sig is freed later so allocate it in the heap */
11308                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor, error);
11309                 if (!is_ok (error)) {
11310                         g_free (sig);
11311                         return NULL;
11312                 }
11313         } else {
11314                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11315         }
11316
11317         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11318         buflen = 256;
11319         p = buffer = (char *)g_malloc (buflen);
11320         /* write the prolog */
11321         *p++ = 1;
11322         *p++ = 0;
11323         for (i = 0; i < sig->param_count; ++i) {
11324                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11325                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
11326                 if (!is_ok (error)) goto leave;
11327         }
11328         i = 0;
11329         if (properties)
11330                 i += mono_array_length (properties);
11331         if (fields)
11332                 i += mono_array_length (fields);
11333         *p++ = i & 0xff;
11334         *p++ = (i >> 8) & 0xff;
11335         if (properties) {
11336                 MonoObject *prop;
11337                 for (i = 0; i < mono_array_length (properties); ++i) {
11338                         MonoType *ptype;
11339                         char *pname;
11340
11341                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11342                         get_prop_name_and_type (prop, &pname, &ptype, error);
11343                         if (!is_ok (error)) goto leave;
11344                         *p++ = 0x54; /* PROPERTY signature */
11345                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
11346                         g_free (pname);
11347                         if (!is_ok (error)) goto leave;
11348                 }
11349         }
11350
11351         if (fields) {
11352                 MonoObject *field;
11353                 for (i = 0; i < mono_array_length (fields); ++i) {
11354                         MonoType *ftype;
11355                         char *fname;
11356
11357                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11358                         get_field_name_and_type (field, &fname, &ftype, error);
11359                         if (!is_ok (error)) goto leave;
11360                         *p++ = 0x53; /* FIELD signature */
11361                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
11362                         g_free (fname);
11363                         if (!is_ok (error)) goto leave;
11364                 }
11365         }
11366
11367         g_assert (p - buffer <= buflen);
11368         buflen = p - buffer;
11369         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11370         p = mono_array_addr (result, char, 0);
11371         memcpy (p, buffer, buflen);
11372 leave:
11373         g_free (buffer);
11374         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11375                 g_free (sig);
11376         return result;
11377 }
11378
11379 /**
11380  * reflection_setup_internal_class:
11381  * @tb: a TypeBuilder object
11382  * @error: set on error
11383  *
11384  * Creates a MonoClass that represents the TypeBuilder.
11385  * This is a trick that lets us simplify a lot of reflection code
11386  * (and will allow us to support Build and Run assemblies easier).
11387  *
11388  * Returns TRUE on success. On failure, returns FALSE and sets @error.
11389  */
11390 static gboolean
11391 reflection_setup_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11392 {
11393         MonoClass *klass, *parent;
11394
11395         mono_error_init (error);
11396         RESOLVE_TYPE (tb->parent, error);
11397         return_val_if_nok (error, FALSE);
11398
11399         mono_loader_lock ();
11400
11401         if (tb->parent) {
11402                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
11403                 if (!is_ok (error)) {
11404                         mono_loader_unlock ();
11405                         return FALSE;
11406                 }
11407                 /* check so we can compile corlib correctly */
11408                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11409                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11410                         parent = parent_type->data.klass;
11411                 } else {
11412                         parent = mono_class_from_mono_type (parent_type);
11413                 }
11414         } else {
11415                 parent = NULL;
11416         }
11417         
11418         /* the type has already being created: it means we just have to change the parent */
11419         if (tb->type.type) {
11420                 klass = mono_class_from_mono_type (tb->type.type);
11421                 klass->parent = NULL;
11422                 /* fool mono_class_setup_parent */
11423                 klass->supertypes = NULL;
11424                 mono_class_setup_parent (klass, parent);
11425                 mono_class_setup_mono_type (klass);
11426                 mono_loader_unlock ();
11427                 return TRUE;
11428         }
11429
11430         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11431
11432         klass->image = &tb->module->dynamic_image->image;
11433
11434         klass->inited = 1; /* we lie to the runtime */
11435         klass->name = mono_string_to_utf8_image (klass->image, tb->name, error);
11436         if (!is_ok (error))
11437                 goto failure;
11438         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, error);
11439         if (!is_ok (error))
11440                 goto failure;
11441         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11442         klass->flags = tb->attrs;
11443         
11444         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11445
11446         klass->element_class = klass;
11447
11448         if (mono_class_get_ref_info (klass) == NULL) {
11449
11450                 mono_class_set_ref_info (klass, tb);
11451
11452                 /* Put into cache so mono_class_get_checked () will find it.
11453                 Skip nested types as those should not be available on the global scope. */
11454                 if (!tb->nesting_type)
11455                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11456
11457                 /*
11458                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11459                 by performing a mono_class_get which does the full resolution.
11460
11461                 Working around this semantics would require us to write a lot of code for no clear advantage.
11462                 */
11463                 mono_image_append_class_to_reflection_info_set (klass);
11464         } else {
11465                 g_assert (mono_class_get_ref_info (klass) == tb);
11466         }
11467
11468         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11469
11470         if (parent != NULL) {
11471                 mono_class_setup_parent (klass, parent);
11472         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11473                 const char *old_n = klass->name;
11474                 /* trick to get relative numbering right when compiling corlib */
11475                 klass->name = "BuildingObject";
11476                 mono_class_setup_parent (klass, mono_defaults.object_class);
11477                 klass->name = old_n;
11478         }
11479
11480         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11481                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11482                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11483                 klass->instance_size = sizeof (MonoObject);
11484                 klass->size_inited = 1;
11485                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11486         }
11487
11488         mono_class_setup_mono_type (klass);
11489
11490         mono_class_setup_supertypes (klass);
11491
11492         /*
11493          * FIXME: handle interfaces.
11494          */
11495
11496         tb->type.type = &klass->byval_arg;
11497
11498         if (tb->nesting_type) {
11499                 g_assert (tb->nesting_type->type);
11500                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, error);
11501                 if (!is_ok (error)) goto failure;
11502                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11503         }
11504
11505         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11506
11507         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11508         
11509         mono_loader_unlock ();
11510         return TRUE;
11511
11512 failure:
11513         mono_loader_unlock ();
11514         return FALSE;
11515 }
11516
11517 /**
11518  * mono_reflection_setup_internal_class:
11519  * @tb: a TypeBuilder object
11520  *
11521  * (icall)
11522  * Creates a MonoClass that represents the TypeBuilder.
11523  * This is a trick that lets us simplify a lot of reflection code
11524  * (and will allow us to support Build and Run assemblies easier).
11525  *
11526  */
11527 void
11528 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11529 {
11530         MonoError error;
11531         (void) reflection_setup_internal_class (tb, &error);
11532         mono_error_set_pending_exception (&error);
11533 }
11534
11535 /*
11536  * mono_reflection_setup_generic_class:
11537  * @tb: a TypeBuilder object
11538  *
11539  * Setup the generic class before adding the first generic parameter.
11540  */
11541 void
11542 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11543 {
11544 }
11545
11546 /*
11547  * mono_reflection_create_generic_class:
11548  * @tb: a TypeBuilder object
11549  *
11550  * Creates the generic class after all generic parameters have been added.
11551  */
11552 void
11553 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11554 {
11555         MonoError error;
11556         MonoClass *klass;
11557         int count, i;
11558
11559         klass = mono_class_from_mono_type (tb->type.type);
11560
11561         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11562
11563         if (klass->generic_container || (count == 0))
11564                 return;
11565
11566         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11567
11568         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11569
11570         klass->generic_container->owner.klass = klass;
11571         klass->generic_container->type_argc = count;
11572         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11573
11574         klass->is_generic = 1;
11575
11576         for (i = 0; i < count; i++) {
11577                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11578                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11579                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11580                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11581                 klass->generic_container->type_params [i] = *param;
11582                 /*Make sure we are a diferent type instance */
11583                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11584                 klass->generic_container->type_params [i].info.pklass = NULL;
11585                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11586
11587                 g_assert (klass->generic_container->type_params [i].param.owner);
11588         }
11589
11590         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11591 }
11592
11593 /**
11594  * reflection_create_internal_class:
11595  * @tb: a TypeBuilder object
11596  * @error: set on error
11597  *
11598  * Actually create the MonoClass that is associated with the TypeBuilder.
11599  * On success returns TRUE, on failure returns FALSE and sets @error.
11600  *
11601  */
11602 static gboolean
11603 reflection_create_internal_class (MonoReflectionTypeBuilder *tb, MonoError *error)
11604 {
11605
11606         MonoClass *klass;
11607
11608         mono_error_init (error);
11609         klass = mono_class_from_mono_type (tb->type.type);
11610
11611         mono_loader_lock ();
11612         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11613                 MonoReflectionFieldBuilder *fb;
11614                 MonoClass *ec;
11615                 MonoType *enum_basetype;
11616
11617                 g_assert (tb->fields != NULL);
11618                 g_assert (mono_array_length (tb->fields) >= 1);
11619
11620                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11621
11622                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11623                 if (!is_ok (error)) {
11624                         mono_loader_unlock ();
11625                         return FALSE;
11626                 }
11627                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11628                         mono_loader_unlock ();
11629                         return TRUE;
11630                 }
11631
11632                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
11633                 if (!is_ok (error)) {
11634                         mono_loader_unlock ();
11635                         return FALSE;
11636                 }
11637                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11638                 if (!klass->element_class)
11639                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11640
11641                 /*
11642                  * get the element_class from the current corlib.
11643                  */
11644                 ec = default_class_from_mono_type (enum_basetype);
11645                 klass->instance_size = ec->instance_size;
11646                 klass->size_inited = 1;
11647                 /* 
11648                  * this is almost safe to do with enums and it's needed to be able
11649                  * to create objects of the enum type (for use in SetConstant).
11650                  */
11651                 /* FIXME: Does this mean enums can't have method overrides ? */
11652                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11653         }
11654         mono_loader_unlock ();
11655         return TRUE;
11656 }
11657
11658 /**
11659  * mono_reflection_create_internal_class:
11660  * @tb: a TypeBuilder object
11661  *
11662  * (icall)
11663  * Actually create the MonoClass that is associated with the TypeBuilder.
11664  */
11665 void
11666 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11667 {
11668         MonoError error;
11669         (void) reflection_create_internal_class (tb, &error);
11670         mono_error_set_pending_exception (&error);
11671 }
11672
11673 static MonoMarshalSpec*
11674 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11675                                 MonoReflectionMarshal *minfo, MonoError *error)
11676 {
11677         MonoMarshalSpec *res;
11678
11679         mono_error_init (error);
11680
11681         res = image_g_new0 (image, MonoMarshalSpec, 1);
11682         res->native = (MonoMarshalNative)minfo->type;
11683
11684         switch (minfo->type) {
11685         case MONO_NATIVE_LPARRAY:
11686                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11687                 if (minfo->has_size) {
11688                         res->data.array_data.param_num = minfo->param_num;
11689                         res->data.array_data.num_elem = minfo->count;
11690                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11691                 }
11692                 else {
11693                         res->data.array_data.param_num = -1;
11694                         res->data.array_data.num_elem = -1;
11695                         res->data.array_data.elem_mult = -1;
11696                 }
11697                 break;
11698
11699         case MONO_NATIVE_BYVALTSTR:
11700         case MONO_NATIVE_BYVALARRAY:
11701                 res->data.array_data.num_elem = minfo->count;
11702                 break;
11703
11704         case MONO_NATIVE_CUSTOM:
11705                 if (minfo->marshaltyperef) {
11706                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
11707                         if (!is_ok (error)) {
11708                                 image_g_free (image, res);
11709                                 return NULL;
11710                         }
11711                         res->data.custom_data.custom_name =
11712                                 type_get_fully_qualified_name (marshaltyperef);
11713                 }
11714                 if (minfo->mcookie)
11715                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11716                 break;
11717
11718         default:
11719                 break;
11720         }
11721
11722         return res;
11723 }
11724 #endif /* !DISABLE_REFLECTION_EMIT */
11725
11726 MonoReflectionMarshalAsAttribute*
11727 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11728                                                         MonoMarshalSpec *spec, MonoError *error)
11729 {
11730         MonoReflectionType *rt;
11731         MonoReflectionMarshalAsAttribute *minfo;
11732         MonoType *mtype;
11733
11734         mono_error_init (error);
11735         
11736         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11737         if (!minfo)
11738                 return NULL;
11739         minfo->utype = spec->native;
11740
11741         switch (minfo->utype) {
11742         case MONO_NATIVE_LPARRAY:
11743                 minfo->array_subtype = spec->data.array_data.elem_type;
11744                 minfo->size_const = spec->data.array_data.num_elem;
11745                 if (spec->data.array_data.param_num != -1)
11746                         minfo->size_param_index = spec->data.array_data.param_num;
11747                 break;
11748
11749         case MONO_NATIVE_BYVALTSTR:
11750         case MONO_NATIVE_BYVALARRAY:
11751                 minfo->size_const = spec->data.array_data.num_elem;
11752                 break;
11753
11754         case MONO_NATIVE_CUSTOM:
11755                 if (spec->data.custom_data.custom_name) {
11756                         mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
11757                         return_val_if_nok  (error, NULL);
11758
11759                         if (mtype) {
11760                                 rt = mono_type_get_object_checked (domain, mtype, error);
11761                                 if (!rt)
11762                                         return NULL;
11763
11764                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11765                         }
11766
11767                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11768                 }
11769                 if (spec->data.custom_data.cookie)
11770                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11771                 break;
11772
11773         default:
11774                 break;
11775         }
11776
11777         return minfo;
11778 }
11779
11780 #ifndef DISABLE_REFLECTION_EMIT
11781 static MonoMethod*
11782 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11783                                          ReflectionMethodBuilder *rmb,
11784                                          MonoMethodSignature *sig)
11785 {
11786         MonoError error;
11787         MonoMethod *m;
11788         MonoMethodWrapper *wrapperm;
11789         MonoMarshalSpec **specs;
11790         MonoReflectionMethodAux *method_aux;
11791         MonoImage *image;
11792         gboolean dynamic;
11793         int i;
11794
11795         mono_error_init (&error);
11796         /*
11797          * Methods created using a MethodBuilder should have their memory allocated
11798          * inside the image mempool, while dynamic methods should have their memory
11799          * malloc'd.
11800          */
11801         dynamic = rmb->refs != NULL;
11802         image = dynamic ? NULL : klass->image;
11803
11804         if (!dynamic)
11805                 g_assert (!klass->generic_class);
11806
11807         mono_loader_lock ();
11808
11809         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11810                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11811                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11812         else
11813                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11814
11815         wrapperm = (MonoMethodWrapper*)m;
11816
11817         m->dynamic = dynamic;
11818         m->slot = -1;
11819         m->flags = rmb->attrs;
11820         m->iflags = rmb->iattrs;
11821         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11822         m->klass = klass;
11823         m->signature = sig;
11824         m->sre_method = TRUE;
11825         m->skip_visibility = rmb->skip_visibility;
11826         if (rmb->table_idx)
11827                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11828
11829         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11830                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11831                         m->string_ctor = 1;
11832
11833                 m->signature->pinvoke = 1;
11834         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11835                 m->signature->pinvoke = 1;
11836
11837                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11838
11839                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11840                 g_assert (mono_error_ok (&error));
11841                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11842                 g_assert (mono_error_ok (&error));
11843                 
11844                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11845
11846                 if (image_is_dynamic (klass->image))
11847                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11848
11849                 mono_loader_unlock ();
11850
11851                 return m;
11852         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11853                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11854                 MonoMethodHeader *header;
11855                 guint32 code_size;
11856                 gint32 max_stack, i;
11857                 gint32 num_locals = 0;
11858                 gint32 num_clauses = 0;
11859                 guint8 *code;
11860
11861                 if (rmb->ilgen) {
11862                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11863                         code_size = rmb->ilgen->code_len;
11864                         max_stack = rmb->ilgen->max_stack;
11865                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11866                         if (rmb->ilgen->ex_handlers)
11867                                 num_clauses = method_count_clauses (rmb->ilgen);
11868                 } else {
11869                         if (rmb->code) {
11870                                 code = mono_array_addr (rmb->code, guint8, 0);
11871                                 code_size = mono_array_length (rmb->code);
11872                                 /* we probably need to run a verifier on the code... */
11873                                 max_stack = 8; 
11874                         }
11875                         else {
11876                                 code = NULL;
11877                                 code_size = 0;
11878                                 max_stack = 8;
11879                         }
11880                 }
11881
11882                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11883                 header->code_size = code_size;
11884                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11885                 memcpy ((char*)header->code, code, code_size);
11886                 header->max_stack = max_stack;
11887                 header->init_locals = rmb->init_locals;
11888                 header->num_locals = num_locals;
11889
11890                 for (i = 0; i < num_locals; ++i) {
11891                         MonoReflectionLocalBuilder *lb = 
11892                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11893
11894                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11895                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11896                         mono_error_assert_ok (&error);
11897                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11898                 }
11899
11900                 header->num_clauses = num_clauses;
11901                 if (num_clauses) {
11902                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11903                                                                  rmb->ilgen, num_clauses, &error);
11904                         mono_error_assert_ok (&error);
11905                 }
11906
11907                 wrapperm->header = header;
11908         }
11909
11910         if (rmb->generic_params) {
11911                 int count = mono_array_length (rmb->generic_params);
11912                 MonoGenericContainer *container = rmb->generic_container;
11913
11914                 g_assert (container);
11915
11916                 container->type_argc = count;
11917                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11918                 container->owner.method = m;
11919                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11920
11921                 m->is_generic = TRUE;
11922                 mono_method_set_generic_container (m, container);
11923
11924                 for (i = 0; i < count; i++) {
11925                         MonoReflectionGenericParam *gp =
11926                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11927                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11928                         mono_error_assert_ok (&error);
11929                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11930                         container->type_params [i] = *param;
11931                 }
11932
11933                 /*
11934                  * The method signature might have pointers to generic parameters that belong to other methods.
11935                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11936                  * generic parameters.
11937                  */
11938                 for (i = 0; i < m->signature->param_count; ++i) {
11939                         MonoType *t = m->signature->params [i];
11940                         if (t->type == MONO_TYPE_MVAR) {
11941                                 MonoGenericParam *gparam =  t->data.generic_param;
11942                                 if (gparam->num < count) {
11943                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11944                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11945                                 }
11946
11947                         }
11948                 }
11949
11950                 if (klass->generic_container) {
11951                         container->parent = klass->generic_container;
11952                         container->context.class_inst = klass->generic_container->context.class_inst;
11953                 }
11954                 container->context.method_inst = mono_get_shared_generic_inst (container);
11955         }
11956
11957         if (rmb->refs) {
11958                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11959                 int i;
11960                 void **data;
11961
11962                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11963
11964                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11965                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11966                 for (i = 0; i < rmb->nrefs; ++i)
11967                         data [i + 1] = rmb->refs [i];
11968         }
11969
11970         method_aux = NULL;
11971
11972         /* Parameter info */
11973         if (rmb->pinfo) {
11974                 if (!method_aux)
11975                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11976                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11977                 for (i = 0; i <= m->signature->param_count; ++i) {
11978                         MonoReflectionParamBuilder *pb;
11979                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11980                                 if ((i > 0) && (pb->attrs)) {
11981                                         /* Make a copy since it might point to a shared type structure */
11982                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11983                                         m->signature->params [i - 1]->attrs = pb->attrs;
11984                                 }
11985
11986                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11987                                         MonoDynamicImage *assembly;
11988                                         guint32 idx, len;
11989                                         MonoTypeEnum def_type;
11990                                         char *p;
11991                                         const char *p2;
11992
11993                                         if (!method_aux->param_defaults) {
11994                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11995                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11996                                         }
11997                                         assembly = (MonoDynamicImage*)klass->image;
11998                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11999                                         /* Copy the data from the blob since it might get realloc-ed */
12000                                         p = assembly->blob.data + idx;
12001                                         len = mono_metadata_decode_blob_size (p, &p2);
12002                                         len += p2 - p;
12003                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
12004                                         method_aux->param_default_types [i] = def_type;
12005                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
12006                                 }
12007
12008                                 if (pb->name) {
12009                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
12010                                         g_assert (mono_error_ok (&error));
12011                                 }
12012                                 if (pb->cattrs) {
12013                                         if (!method_aux->param_cattr)
12014                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
12015                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
12016                                 }
12017                         }
12018                 }
12019         }
12020
12021         /* Parameter marshalling */
12022         specs = NULL;
12023         if (rmb->pinfo)         
12024                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
12025                         MonoReflectionParamBuilder *pb;
12026                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
12027                                 if (pb->marshal_info) {
12028                                         if (specs == NULL)
12029                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
12030                                         specs [pb->position] = 
12031                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, &error);
12032                                         if (!is_ok (&error)) {
12033                                                 mono_loader_unlock ();
12034                                                 image_g_free (image, specs);
12035                                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12036                                         }
12037                                 }
12038                         }
12039                 }
12040         if (specs != NULL) {
12041                 if (!method_aux)
12042                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
12043                 method_aux->param_marshall = specs;
12044         }
12045
12046         if (image_is_dynamic (klass->image) && method_aux)
12047                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
12048
12049         mono_loader_unlock ();
12050
12051         return m;
12052 }       
12053
12054 static MonoMethod*
12055 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
12056 {
12057         ReflectionMethodBuilder rmb;
12058         MonoMethodSignature *sig;
12059
12060         mono_loader_lock ();
12061         g_assert (klass->image != NULL);
12062         sig = ctor_builder_to_signature (klass->image, mb, error);
12063         mono_loader_unlock ();
12064         return_val_if_nok (error, NULL);
12065
12066         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
12067                 return NULL;
12068
12069         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12070         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12071
12072         /* If we are in a generic class, we might be called multiple times from inflate_method */
12073         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12074                 /* ilgen is no longer needed */
12075                 mb->ilgen = NULL;
12076         }
12077
12078         return mb->mhandle;
12079 }
12080
12081 static MonoMethod*
12082 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
12083 {
12084         ReflectionMethodBuilder rmb;
12085         MonoMethodSignature *sig;
12086
12087         mono_error_init (error);
12088
12089         mono_loader_lock ();
12090         g_assert (klass->image != NULL);
12091         sig = method_builder_to_signature (klass->image, mb, error);
12092         mono_loader_unlock ();
12093         return_val_if_nok (error, NULL);
12094
12095         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
12096                 return NULL;
12097
12098         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12099         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
12100
12101         /* If we are in a generic class, we might be called multiple times from inflate_method */
12102         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
12103                 /* ilgen is no longer needed */
12104                 mb->ilgen = NULL;
12105         }
12106         return mb->mhandle;
12107 }
12108
12109 static MonoClassField*
12110 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
12111 {
12112         MonoClassField *field;
12113         MonoType *custom;
12114
12115         mono_error_init (error);
12116
12117         field = g_new0 (MonoClassField, 1);
12118
12119         field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
12120         mono_error_assert_ok (error);
12121         if (fb->attrs || fb->modreq || fb->modopt) {
12122                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12123                 if (!is_ok (error)) {
12124                         g_free (field);
12125                         return NULL;
12126                 }
12127                 field->type = mono_metadata_type_dup (NULL, type);
12128                 field->type->attrs = fb->attrs;
12129
12130                 g_assert (image_is_dynamic (klass->image));
12131                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
12132                 g_free (field->type);
12133                 if (!is_ok (error)) {
12134                         g_free (field);
12135                         return NULL;
12136                 }
12137                 field->type = mono_metadata_type_dup (klass->image, custom);
12138                 g_free (custom);
12139         } else {
12140                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12141                 if (!is_ok (error)) {
12142                         g_free (field);
12143                         return NULL;
12144                 }
12145         }
12146         if (fb->offset != -1)
12147                 field->offset = fb->offset;
12148         field->parent = klass;
12149         mono_save_custom_attrs (klass->image, field, fb->cattrs);
12150
12151         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
12152
12153         return field;
12154 }
12155 #endif
12156
12157 /**
12158  * mono_reflection_bind_generic_parameters:
12159  * @type: a managed type object (which should be some kind of generic (instance? definition?))
12160  * @type_args: the number of type arguments to bind
12161  * @types: array of type arguments
12162  * @error: set on error
12163  *
12164  * Given a managed type object for a generic type instance, binds each of its arguments to the specified types.
12165  * Returns the MonoType* for the resulting type instantiation.  On failure returns NULL and sets @error.
12166  */
12167 MonoType*
12168 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types, MonoError *error)
12169 {
12170         MonoClass *klass;
12171         MonoReflectionTypeBuilder *tb = NULL;
12172         gboolean is_dynamic = FALSE;
12173         MonoClass *geninst;
12174
12175         mono_error_init (error);
12176         
12177         mono_loader_lock ();
12178
12179         if (is_sre_type_builder (mono_object_class (type))) {
12180                 tb = (MonoReflectionTypeBuilder *) type;
12181
12182                 is_dynamic = TRUE;
12183         } else if (is_sre_generic_instance (mono_object_class (type))) {
12184                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
12185                 MonoReflectionType *gtd = rgi->generic_type;
12186
12187                 if (is_sre_type_builder (mono_object_class (gtd))) {
12188                         tb = (MonoReflectionTypeBuilder *)gtd;
12189                         is_dynamic = TRUE;
12190                 }
12191         }
12192
12193         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
12194         if (tb && tb->generic_container)
12195                 mono_reflection_create_generic_class (tb);
12196
12197         MonoType *t = mono_reflection_type_get_handle (type, error);
12198         if (!is_ok (error)) {
12199                 mono_loader_unlock ();
12200                 return NULL;
12201         }
12202
12203         klass = mono_class_from_mono_type (t);
12204         if (!klass->generic_container) {
12205                 mono_loader_unlock ();
12206                 mono_error_set_type_load_class (error, klass, "Cannot bind generic parameters of a non-generic type");
12207                 return NULL;
12208         }
12209
12210         if (klass->wastypebuilder) {
12211                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
12212
12213                 is_dynamic = TRUE;
12214         }
12215
12216         mono_loader_unlock ();
12217
12218         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
12219
12220         return &geninst->byval_arg;
12221 }
12222
12223 MonoClass*
12224 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
12225 {
12226         MonoGenericClass *gclass;
12227         MonoGenericInst *inst;
12228
12229         g_assert (klass->generic_container);
12230
12231         inst = mono_metadata_get_generic_inst (type_argc, types);
12232         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
12233
12234         return mono_generic_class_get_class (gclass);
12235 }
12236
12237 MonoReflectionMethod*
12238 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
12239 {
12240         MonoError error;
12241         MonoClass *klass;
12242         MonoMethod *method, *inflated;
12243         MonoMethodInflated *imethod;
12244         MonoGenericContext tmp_context;
12245         MonoGenericInst *ginst;
12246         MonoType **type_argv;
12247         int count, i;
12248
12249         /*FIXME but this no longer should happen*/
12250         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
12251 #ifndef DISABLE_REFLECTION_EMIT
12252                 MonoReflectionMethodBuilder *mb = NULL;
12253                 MonoType *tb;
12254                 MonoClass *klass;
12255
12256                 mb = (MonoReflectionMethodBuilder *) rmethod;
12257                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
12258                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12259                 klass = mono_class_from_mono_type (tb);
12260
12261                 method = methodbuilder_to_mono_method (klass, mb, &error);
12262                 if (!method)
12263                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12264 #else
12265                 g_assert_not_reached ();
12266                 method = NULL;
12267 #endif
12268         } else {
12269                 method = rmethod->method;
12270         }
12271
12272         klass = method->klass;
12273
12274         if (method->is_inflated)
12275                 method = ((MonoMethodInflated *) method)->declaring;
12276
12277         count = mono_method_signature (method)->generic_param_count;
12278         if (count != mono_array_length (types))
12279                 return NULL;
12280
12281         type_argv = g_new0 (MonoType *, count);
12282         for (i = 0; i < count; i++) {
12283                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12284                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12285                 if (!is_ok (&error)) {
12286                         g_free (type_argv);
12287                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12288                 }
12289         }
12290         ginst = mono_metadata_get_generic_inst (count, type_argv);
12291         g_free (type_argv);
12292
12293         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12294         tmp_context.method_inst = ginst;
12295
12296         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12297         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12298         imethod = (MonoMethodInflated *) inflated;
12299
12300         /*FIXME but I think this is no longer necessary*/
12301         if (image_is_dynamic (method->klass->image)) {
12302                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12303                 /*
12304                  * This table maps metadata structures representing inflated methods/fields
12305                  * to the reflection objects representing their generic definitions.
12306                  */
12307                 mono_image_lock ((MonoImage*)image);
12308                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12309                 mono_image_unlock ((MonoImage*)image);
12310         }
12311
12312         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12313                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12314         
12315         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12316         mono_error_raise_exception (&error); /* FIXME don't raise here */
12317         return ret;
12318 }
12319
12320 #ifndef DISABLE_REFLECTION_EMIT
12321
12322 static MonoMethod *
12323 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12324 {
12325         MonoMethodInflated *imethod;
12326         MonoGenericContext *context;
12327         int i;
12328
12329         /*
12330          * With generic code sharing the klass might not be inflated.
12331          * This can happen because classes inflated with their own
12332          * type arguments are "normalized" to the uninflated class.
12333          */
12334         if (!klass->generic_class)
12335                 return method;
12336
12337         context = mono_class_get_context (klass);
12338
12339         if (klass->method.count && klass->methods) {
12340                 /* Find the already created inflated method */
12341                 for (i = 0; i < klass->method.count; ++i) {
12342                         g_assert (klass->methods [i]->is_inflated);
12343                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12344                                 break;
12345                 }
12346                 g_assert (i < klass->method.count);
12347                 imethod = (MonoMethodInflated*)klass->methods [i];
12348         } else {
12349                 MonoError error;
12350                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12351                 mono_error_assert_ok (&error);
12352         }
12353
12354         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12355                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12356
12357                 mono_image_lock ((MonoImage*)image);
12358                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12359                 mono_image_unlock ((MonoImage*)image);
12360         }
12361         return (MonoMethod *) imethod;
12362 }
12363
12364 static MonoMethod *
12365 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12366 {
12367         MonoMethod *method;
12368         MonoClass *gklass;
12369
12370         mono_error_init (error);
12371
12372         MonoClass *type_class = mono_object_class (type);
12373
12374         if (is_sre_generic_instance (type_class)) {
12375                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12376                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12377                 return_val_if_nok (error, NULL);
12378                 gklass = mono_class_from_mono_type (generic_type);
12379         } else if (is_sre_type_builder (type_class)) {
12380                 MonoType *t = mono_reflection_type_get_handle (type, error);
12381                 return_val_if_nok (error, NULL);
12382                 gklass = mono_class_from_mono_type (t);
12383         } else if (type->type) {
12384                 gklass = mono_class_from_mono_type (type->type);
12385                 gklass = mono_class_get_generic_type_definition (gklass);
12386         } else {
12387                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12388         }
12389
12390         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12391                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12392                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12393                 else {
12394                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12395                         if (!method)
12396                                 return NULL;
12397                 }
12398         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12399                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12400                 if (!method)
12401                         return NULL;
12402         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12403                 method = ((MonoReflectionMethod *) obj)->method;
12404         else {
12405                 method = NULL; /* prevent compiler warning */
12406                 g_error ("can't handle type %s", obj->vtable->klass->name);
12407         }
12408
12409         MonoType *t = mono_reflection_type_get_handle (type, error);
12410         return_val_if_nok (error, NULL);
12411         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12412 }
12413
12414 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12415 static gboolean
12416 reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields, MonoError *error)
12417 {
12418         MonoGenericClass *gclass;
12419         MonoDynamicGenericClass *dgclass;
12420         MonoClass *klass, *gklass;
12421         MonoType *gtype;
12422         int i;
12423
12424         mono_error_init (error);
12425
12426         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, error);
12427         return_val_if_nok (error, FALSE);
12428         klass = mono_class_from_mono_type (gtype);
12429         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12430         gclass = gtype->data.generic_class;
12431
12432         if (!gclass->is_dynamic)
12433                 return TRUE;
12434
12435         dgclass = (MonoDynamicGenericClass *) gclass;
12436
12437         if (dgclass->initialized)
12438                 return TRUE;
12439
12440         gklass = gclass->container_class;
12441         mono_class_init (gklass);
12442
12443         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12444
12445         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12446         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12447         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12448
12449         for (i = 0; i < dgclass->count_fields; i++) {
12450                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12451                 MonoClassField *field, *inflated_field = NULL;
12452
12453                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
12454                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj, error);
12455                         return_val_if_nok (error, FALSE);
12456                 } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12457                         field = ((MonoReflectionField *) obj)->field;
12458                 else {
12459                         field = NULL; /* prevent compiler warning */
12460                         g_assert_not_reached ();
12461                 }
12462
12463                 dgclass->fields [i] = *field;
12464                 dgclass->fields [i].parent = klass;
12465                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12466                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), error);
12467                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
12468                 dgclass->field_generic_types [i] = field->type;
12469                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12470                 dgclass->field_objects [i] = obj;
12471
12472                 if (inflated_field) {
12473                         g_free (inflated_field);
12474                 } else {
12475                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12476                 }
12477         }
12478
12479         dgclass->initialized = TRUE;
12480         return TRUE;
12481 }
12482
12483 void
12484 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12485 {
12486         MonoError error;
12487         (void) reflection_generic_class_initialize (type, fields, &error);
12488         mono_error_set_pending_exception (&error);
12489 }
12490
12491 void
12492 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12493 {
12494         MonoDynamicGenericClass *dgclass;
12495         int i;
12496
12497         g_assert (gclass->is_dynamic);
12498
12499         dgclass = (MonoDynamicGenericClass *)gclass;
12500
12501         for (i = 0; i < dgclass->count_fields; ++i) {
12502                 MonoClassField *field = dgclass->fields + i;
12503                 mono_metadata_free_type (field->type);
12504                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12505         }
12506 }
12507
12508 /**
12509  * fix_partial_generic_class:
12510  * @klass: a generic instantiation MonoClass
12511  * @error: set on error
12512  *
12513  * Assumes that the generic container of @klass has its vtable
12514  * initialized, and updates the parent class, insterfaces, methods and
12515  * fields of @klass by inflating the types using the generic context.
12516  *
12517  * On success returns TRUE, on failure returns FALSE and sets @error.
12518  *
12519  */
12520 static gboolean
12521 fix_partial_generic_class (MonoClass *klass, MonoError *error)
12522 {
12523         MonoClass *gklass = klass->generic_class->container_class;
12524         MonoDynamicGenericClass *dgclass;
12525         int i;
12526
12527         mono_error_init (error);
12528
12529         if (klass->wastypebuilder)
12530                 return TRUE;
12531
12532         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12533         if (klass->parent != gklass->parent) {
12534                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, error);
12535                 if (mono_error_ok (error)) {
12536                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12537                         mono_metadata_free_type (parent_type);
12538                         if (parent != klass->parent) {
12539                                 /*fool mono_class_setup_parent*/
12540                                 klass->supertypes = NULL;
12541                                 mono_class_setup_parent (klass, parent);
12542                         }
12543                 } else {
12544                         if (gklass->wastypebuilder)
12545                                 klass->wastypebuilder = TRUE;
12546                         return FALSE;
12547                 }
12548         }
12549
12550         if (!dgclass->initialized)
12551                 return TRUE;
12552
12553         if (klass->method.count != gklass->method.count) {
12554                 klass->method.count = gklass->method.count;
12555                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12556
12557                 for (i = 0; i < klass->method.count; i++) {
12558                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12559                                 gklass->methods [i], klass, mono_class_get_context (klass), error);
12560                         mono_error_assert_ok (error);
12561                 }
12562         }
12563
12564         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12565                 klass->interface_count = gklass->interface_count;
12566                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12567                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12568
12569                 for (i = 0; i < gklass->interface_count; ++i) {
12570                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
12571                         return_val_if_nok (error, FALSE);
12572
12573                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12574                         mono_metadata_free_type (iface_type);
12575
12576                         if (!ensure_runtime_vtable (klass->interfaces [i], error))
12577                                 return FALSE;
12578                 }
12579                 klass->interfaces_inited = 1;
12580         }
12581
12582         if (klass->field.count != gklass->field.count) {
12583                 klass->field.count = gklass->field.count;
12584                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12585
12586                 for (i = 0; i < klass->field.count; i++) {
12587                         klass->fields [i] = gklass->fields [i];
12588                         klass->fields [i].parent = klass;
12589                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
12590                         return_val_if_nok (error, FALSE);
12591                 }
12592         }
12593
12594         /*We can only finish with this klass once it's parent has as well*/
12595         if (gklass->wastypebuilder)
12596                 klass->wastypebuilder = TRUE;
12597         return TRUE;
12598 }
12599
12600 /**
12601  * ensure_generic_class_runtime_vtable:
12602  * @klass a generic class
12603  * @error set on error
12604  *
12605  * Ensures that the generic container of @klass has a vtable and
12606  * returns TRUE on success.  On error returns FALSE and sets @error.
12607  */
12608 static gboolean
12609 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12610 {
12611         MonoClass *gklass = klass->generic_class->container_class;
12612
12613         mono_error_init (error);
12614
12615         if (!ensure_runtime_vtable (gklass, error))
12616                 return FALSE;
12617
12618         return fix_partial_generic_class (klass, error);
12619 }
12620
12621 /**
12622  * ensure_runtime_vtable:
12623  * @klass the class
12624  * @error set on error
12625  *
12626  * Ensures that @klass has a vtable and returns TRUE on success. On
12627  * error returns FALSE and sets @error.
12628  */
12629 static gboolean
12630 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12631 {
12632         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12633         int i, num, j;
12634
12635         mono_error_init (error);
12636
12637         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12638                 return TRUE;
12639         if (klass->parent)
12640                 if (!ensure_runtime_vtable (klass->parent, error))
12641                         return FALSE;
12642
12643         if (tb) {
12644                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12645                 num += tb->num_methods;
12646                 klass->method.count = num;
12647                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12648                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12649                 for (i = 0; i < num; ++i) {
12650                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12651                         if (!ctor)
12652                                 return FALSE;
12653                         klass->methods [i] = ctor;
12654                 }
12655                 num = tb->num_methods;
12656                 j = i;
12657                 for (i = 0; i < num; ++i) {
12658                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12659                         if (!meth)
12660                                 return FALSE;
12661                         klass->methods [j++] = meth;
12662                 }
12663         
12664                 if (tb->interfaces) {
12665                         klass->interface_count = mono_array_length (tb->interfaces);
12666                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12667                         for (i = 0; i < klass->interface_count; ++i) {
12668                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12669                                 return_val_if_nok (error, FALSE);
12670                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12671                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12672                                         return FALSE;
12673                         }
12674                         klass->interfaces_inited = 1;
12675                 }
12676         } else if (klass->generic_class){
12677                 if (!ensure_generic_class_runtime_vtable (klass, error)) {
12678                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12679                         return FALSE;
12680                 }
12681         }
12682
12683         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12684                 int slot_num = 0;
12685                 for (i = 0; i < klass->method.count; ++i) {
12686                         MonoMethod *im = klass->methods [i];
12687                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12688                                 im->slot = slot_num++;
12689                 }
12690                 
12691                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12692                 mono_class_setup_interface_offsets (klass);
12693                 mono_class_setup_interface_id (klass);
12694         }
12695
12696         /*
12697          * The generic vtable is needed even if image->run is not set since some
12698          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12699          * method->slot being defined.
12700          */
12701
12702         /* 
12703          * tb->methods could not be freed since it is used for determining 
12704          * overrides during dynamic vtable construction.
12705          */
12706
12707         return TRUE;
12708 }
12709
12710 static MonoMethod*
12711 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
12712 {
12713         mono_error_init (error);
12714         MonoClass *klass = mono_object_class (method);
12715         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12716                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12717                 return sr_method->method;
12718         }
12719         if (is_sre_method_builder (klass)) {
12720                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12721                 return mb->mhandle;
12722         }
12723         if (is_sre_method_on_tb_inst (klass)) {
12724                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12725                 MonoMethod *result;
12726                 /*FIXME move this to a proper method and unify with resolve_object*/
12727                 if (m->method_args) {
12728                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
12729                 } else {
12730                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
12731                         return_val_if_nok (error, NULL);
12732                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12733                         MonoMethod *mono_method;
12734
12735                         if (is_sre_method_builder (mono_object_class (m->mb)))
12736                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12737                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12738                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12739                         else
12740                                 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)));
12741
12742                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12743                 }
12744                 return result;
12745         }
12746
12747         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12748         return NULL;
12749 }
12750
12751 void
12752 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
12753 {
12754         MonoReflectionTypeBuilder *tb;
12755         int i, j, onum;
12756         MonoReflectionMethod *m;
12757
12758         mono_error_init (error);
12759         *overrides = NULL;
12760         *num_overrides = 0;
12761
12762         g_assert (image_is_dynamic (klass->image));
12763
12764         if (!mono_class_get_ref_info (klass))
12765                 return;
12766
12767         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12768
12769         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12770
12771         onum = 0;
12772         if (tb->methods) {
12773                 for (i = 0; i < tb->num_methods; ++i) {
12774                         MonoReflectionMethodBuilder *mb = 
12775                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12776                         if (mb->override_methods)
12777                                 onum += mono_array_length (mb->override_methods);
12778                 }
12779         }
12780
12781         if (onum) {
12782                 *overrides = g_new0 (MonoMethod*, onum * 2);
12783
12784                 onum = 0;
12785                 for (i = 0; i < tb->num_methods; ++i) {
12786                         MonoReflectionMethodBuilder *mb = 
12787                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12788                         if (mb->override_methods) {
12789                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12790                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12791
12792                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
12793                                         return_if_nok (error);
12794                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12795
12796                                         g_assert (mb->mhandle);
12797
12798                                         onum ++;
12799                                 }
12800                         }
12801                 }
12802         }
12803
12804         *num_overrides = onum;
12805 }
12806
12807 static void
12808 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12809 {
12810         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12811         MonoReflectionFieldBuilder *fb;
12812         MonoClassField *field;
12813         MonoImage *image = klass->image;
12814         const char *p, *p2;
12815         int i;
12816         guint32 len, idx, real_size = 0;
12817
12818         klass->field.count = tb->num_fields;
12819         klass->field.first = 0;
12820
12821         mono_error_init (error);
12822
12823         if (tb->class_size) {
12824                 if ((tb->packing_size & 0xffffff00) != 0) {
12825                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12826                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12827                         return;
12828                 }
12829                 klass->packing_size = tb->packing_size;
12830                 real_size = klass->instance_size + tb->class_size;
12831         }
12832
12833         if (!klass->field.count) {
12834                 klass->instance_size = MAX (klass->instance_size, real_size);
12835                 return;
12836         }
12837         
12838         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12839         mono_class_alloc_ext (klass);
12840         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12841         /*
12842         This is, guess what, a hack.
12843         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12844         On the static path no field class is resolved, only types are built. This is the right thing to do
12845         but we suck.
12846         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12847         */
12848         klass->size_inited = 1;
12849
12850         for (i = 0; i < klass->field.count; ++i) {
12851                 MonoArray *rva_data;
12852                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12853                 field = &klass->fields [i];
12854                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12855                 if (!mono_error_ok (error))
12856                         return;
12857                 if (fb->attrs) {
12858                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12859                         return_if_nok (error);
12860                         field->type = mono_metadata_type_dup (klass->image, type);
12861                         field->type->attrs = fb->attrs;
12862                 } else {
12863                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12864                         return_if_nok (error);
12865                 }
12866
12867                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12868                         char *base = mono_array_addr (rva_data, char, 0);
12869                         size_t size = mono_array_length (rva_data);
12870                         char *data = (char *)mono_image_alloc (klass->image, size);
12871                         memcpy (data, base, size);
12872                         klass->ext->field_def_values [i].data = data;
12873                 }
12874                 if (fb->offset != -1)
12875                         field->offset = fb->offset;
12876                 field->parent = klass;
12877                 fb->handle = field;
12878                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12879
12880                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12881                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12882                 }
12883                 if (fb->def_value) {
12884                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12885                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12886                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12887                         /* Copy the data from the blob since it might get realloc-ed */
12888                         p = assembly->blob.data + idx;
12889                         len = mono_metadata_decode_blob_size (p, &p2);
12890                         len += p2 - p;
12891                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12892                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12893                 }
12894         }
12895
12896         klass->instance_size = MAX (klass->instance_size, real_size);
12897         mono_class_layout_fields (klass, klass->instance_size);
12898 }
12899
12900 static void
12901 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12902 {
12903         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12904         MonoReflectionPropertyBuilder *pb;
12905         MonoImage *image = klass->image;
12906         MonoProperty *properties;
12907         int i;
12908
12909         mono_error_init (error);
12910
12911         if (!klass->ext)
12912                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12913
12914         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12915         klass->ext->property.first = 0;
12916
12917         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12918         klass->ext->properties = properties;
12919         for (i = 0; i < klass->ext->property.count; ++i) {
12920                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12921                 properties [i].parent = klass;
12922                 properties [i].attrs = pb->attrs;
12923                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12924                 if (!mono_error_ok (error))
12925                         return;
12926                 if (pb->get_method)
12927                         properties [i].get = pb->get_method->mhandle;
12928                 if (pb->set_method)
12929                         properties [i].set = pb->set_method->mhandle;
12930
12931                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12932                 if (pb->def_value) {
12933                         guint32 len, idx;
12934                         const char *p, *p2;
12935                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12936                         if (!klass->ext->prop_def_values)
12937                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12938                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12939                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12940                         /* Copy the data from the blob since it might get realloc-ed */
12941                         p = assembly->blob.data + idx;
12942                         len = mono_metadata_decode_blob_size (p, &p2);
12943                         len += p2 - p;
12944                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12945                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12946                 }
12947         }
12948 }
12949
12950 static MonoReflectionEvent *
12951 reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb, MonoError *error)
12952 {
12953         mono_error_init (error);
12954
12955         MonoEvent *event = g_new0 (MonoEvent, 1);
12956         MonoClass *klass;
12957
12958         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
12959         if (!is_ok (error)) {
12960                 g_free (event);
12961                 return NULL;
12962         }
12963         klass = mono_class_from_mono_type (type);
12964
12965         event->parent = klass;
12966         event->attrs = eb->attrs;
12967         event->name = mono_string_to_utf8 (eb->name);
12968         if (eb->add_method)
12969                 event->add = eb->add_method->mhandle;
12970         if (eb->remove_method)
12971                 event->remove = eb->remove_method->mhandle;
12972         if (eb->raise_method)
12973                 event->raise = eb->raise_method->mhandle;
12974
12975 #ifndef MONO_SMALL_CONFIG
12976         if (eb->other_methods) {
12977                 int j;
12978                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12979                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12980                         MonoReflectionMethodBuilder *mb = 
12981                                 mono_array_get (eb->other_methods,
12982                                                 MonoReflectionMethodBuilder*, j);
12983                         event->other [j] = mb->mhandle;
12984                 }
12985         }
12986 #endif
12987
12988         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, error);
12989         if (!is_ok (error)) {
12990 #ifndef MONO_SMALL_CONFIG
12991                 g_free (event->other);
12992 #endif
12993                 g_free (event);
12994                 return NULL;
12995         }
12996         return ev_obj;
12997 }
12998
12999 MonoReflectionEvent *
13000 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13001 {
13002         MonoError error;
13003         MonoReflectionEvent *result = reflection_event_builder_get_event_info (tb, eb, &error);
13004         mono_error_set_pending_exception (&error);
13005         return result;
13006 }
13007
13008 static void
13009 typebuilder_setup_events (MonoClass *klass, MonoError *error)
13010 {
13011         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13012         MonoReflectionEventBuilder *eb;
13013         MonoImage *image = klass->image;
13014         MonoEvent *events;
13015         int i;
13016
13017         mono_error_init (error);
13018
13019         if (!klass->ext)
13020                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
13021
13022         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
13023         klass->ext->event.first = 0;
13024
13025         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
13026         klass->ext->events = events;
13027         for (i = 0; i < klass->ext->event.count; ++i) {
13028                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
13029                 events [i].parent = klass;
13030                 events [i].attrs = eb->attrs;
13031                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
13032                 if (!mono_error_ok (error))
13033                         return;
13034                 if (eb->add_method)
13035                         events [i].add = eb->add_method->mhandle;
13036                 if (eb->remove_method)
13037                         events [i].remove = eb->remove_method->mhandle;
13038                 if (eb->raise_method)
13039                         events [i].raise = eb->raise_method->mhandle;
13040
13041 #ifndef MONO_SMALL_CONFIG
13042                 if (eb->other_methods) {
13043                         int j;
13044                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
13045                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
13046                                 MonoReflectionMethodBuilder *mb = 
13047                                         mono_array_get (eb->other_methods,
13048                                                                         MonoReflectionMethodBuilder*, j);
13049                                 events [i].other [j] = mb->mhandle;
13050                         }
13051                 }
13052 #endif
13053                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
13054         }
13055 }
13056
13057 struct remove_instantiations_user_data
13058 {
13059         MonoClass *klass;
13060         MonoError *error;
13061 };
13062
13063 static gboolean
13064 remove_instantiations_of_and_ensure_contents (gpointer key,
13065                                                   gpointer value,
13066                                                   gpointer user_data)
13067 {
13068         struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
13069         MonoType *type = (MonoType*)key;
13070         MonoClass *klass = data->klass;
13071         gboolean already_failed = !is_ok (data->error);
13072         MonoError lerror;
13073         MonoError *error = already_failed ? &lerror : data->error;
13074
13075         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
13076                 MonoClass *inst_klass = mono_class_from_mono_type (type);
13077                 //Ensure it's safe to use it.
13078                 if (!fix_partial_generic_class (inst_klass, error)) {
13079                         mono_class_set_failure (inst_klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13080                         // Marked the class with failure, but since some other instantiation already failed,
13081                         // just report that one, and swallow the error from this one.
13082                         if (already_failed)
13083                                 mono_error_cleanup (error);
13084                 }
13085                 return TRUE;
13086         } else
13087                 return FALSE;
13088 }
13089
13090 static void
13091 check_array_for_usertypes (MonoArray *arr, MonoError *error)
13092 {
13093         mono_error_init (error);
13094         int i;
13095
13096         if (!arr)
13097                 return;
13098
13099         for (i = 0; i < mono_array_length (arr); ++i) {
13100                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
13101                 if (!mono_error_ok (error))
13102                         break;
13103         }
13104 }
13105
13106 MonoReflectionType*
13107 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13108 {
13109         MonoError error;
13110         MonoClass *klass;
13111         MonoDomain* domain;
13112         MonoReflectionType* res;
13113         int i, j;
13114
13115         mono_error_init (&error);
13116
13117         domain = mono_object_domain (tb);
13118         klass = mono_class_from_mono_type (tb->type.type);
13119
13120         /*
13121          * Check for user defined Type subclasses.
13122          */
13123         RESOLVE_TYPE (tb->parent, &error);
13124         if (!is_ok (&error))
13125                 goto failure_unlocked;
13126         check_array_for_usertypes (tb->interfaces, &error);
13127         if (!is_ok (&error))
13128                 goto failure_unlocked;
13129         if (tb->fields) {
13130                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
13131                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
13132                         if (fb) {
13133                                 RESOLVE_TYPE (fb->type, &error);
13134                                 if (!is_ok (&error))
13135                                         goto failure_unlocked;
13136                                 check_array_for_usertypes (fb->modreq, &error);
13137                                 if (!is_ok (&error))
13138                                         goto failure_unlocked;
13139                                 check_array_for_usertypes (fb->modopt, &error);
13140                                 if (!is_ok (&error))
13141                                         goto failure_unlocked;
13142                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
13143                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
13144                                         if (!is_ok (&error))
13145                                                 goto failure_unlocked;
13146                                 }
13147                         }
13148                 }
13149         }
13150         if (tb->methods) {
13151                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
13152                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
13153                         if (mb) {
13154                                 RESOLVE_TYPE (mb->rtype, &error);
13155                                 if (!is_ok (&error))
13156                                         goto failure_unlocked;
13157                                 check_array_for_usertypes (mb->return_modreq, &error);
13158                                 if (!is_ok (&error))
13159                                         goto failure_unlocked;
13160                                 check_array_for_usertypes (mb->return_modopt, &error);
13161                                 if (!is_ok (&error))
13162                                         goto failure_unlocked;
13163                                 check_array_for_usertypes (mb->parameters, &error);
13164                                 if (!is_ok (&error))
13165                                         goto failure_unlocked;
13166                                 if (mb->param_modreq)
13167                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13168                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13169                                                 if (!is_ok (&error))
13170                                                         goto failure_unlocked;
13171                                         }
13172                                 if (mb->param_modopt)
13173                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13174                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13175                                                 if (!is_ok (&error))
13176                                                         goto failure_unlocked;
13177                                         }
13178                         }
13179                 }
13180         }
13181         if (tb->ctors) {
13182                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
13183                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
13184                         if (mb) {
13185                                 check_array_for_usertypes (mb->parameters, &error);
13186                                 if (!is_ok (&error))
13187                                         goto failure_unlocked;
13188                                 if (mb->param_modreq)
13189                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
13190                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
13191                                                 if (!is_ok (&error))
13192                                                         goto failure_unlocked;
13193                                         }
13194                                 if (mb->param_modopt)
13195                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
13196                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
13197                                                 if (!is_ok (&error))
13198                                                         goto failure_unlocked;
13199                                         }
13200                         }
13201                 }
13202         }
13203
13204         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
13205
13206         /* 
13207          * we need to lock the domain because the lock will be taken inside
13208          * So, we need to keep the locking order correct.
13209          */
13210         mono_loader_lock ();
13211         mono_domain_lock (domain);
13212         if (klass->wastypebuilder) {
13213                 mono_domain_unlock (domain);
13214                 mono_loader_unlock ();
13215
13216                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13217                 mono_error_set_pending_exception (&error);
13218
13219                 return res;
13220         }
13221         /*
13222          * Fields to set in klass:
13223          * the various flags: delegate/unicode/contextbound etc.
13224          */
13225         klass->flags = tb->attrs;
13226         klass->has_cctor = 1;
13227         klass->has_finalize = 1;
13228         klass->has_finalize_inited = 1;
13229
13230         mono_class_setup_parent (klass, klass->parent);
13231         /* fool mono_class_setup_supertypes */
13232         klass->supertypes = NULL;
13233         mono_class_setup_supertypes (klass);
13234         mono_class_setup_mono_type (klass);
13235
13236 #if 0
13237         if (!((MonoDynamicImage*)klass->image)->run) {
13238                 if (klass->generic_container) {
13239                         /* FIXME: The code below can't handle generic classes */
13240                         klass->wastypebuilder = TRUE;
13241                         mono_loader_unlock ();
13242                         mono_domain_unlock (domain);
13243
13244                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13245                         mono_error_set_pending_exception (&error);
13246
13247                         return res;
13248                 }
13249         }
13250 #endif
13251
13252         /* enums are done right away */
13253         if (!klass->enumtype)
13254                 if (!ensure_runtime_vtable (klass, &error))
13255                         goto failure;
13256
13257         if (tb->subtypes) {
13258                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
13259                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
13260                         mono_class_alloc_ext (klass);
13261                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
13262                         if (!is_ok (&error)) goto failure;
13263                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
13264                 }
13265         }
13266
13267         klass->nested_classes_inited = TRUE;
13268
13269         /* fields and object layout */
13270         if (klass->parent) {
13271                 if (!klass->parent->size_inited)
13272                         mono_class_init (klass->parent);
13273                 klass->instance_size = klass->parent->instance_size;
13274                 klass->sizes.class_size = 0;
13275                 klass->min_align = klass->parent->min_align;
13276                 /* if the type has no fields we won't call the field_setup
13277                  * routine which sets up klass->has_references.
13278                  */
13279                 klass->has_references |= klass->parent->has_references;
13280         } else {
13281                 klass->instance_size = sizeof (MonoObject);
13282                 klass->min_align = 1;
13283         }
13284
13285         /* FIXME: handle packing_size and instance_size */
13286         typebuilder_setup_fields (klass, &error);
13287         if (!mono_error_ok (&error))
13288                 goto failure;
13289         typebuilder_setup_properties (klass, &error);
13290         if (!mono_error_ok (&error))
13291                 goto failure;
13292
13293         typebuilder_setup_events (klass, &error);
13294         if (!mono_error_ok (&error))
13295                 goto failure;
13296
13297         klass->wastypebuilder = TRUE;
13298
13299         /* 
13300          * If we are a generic TypeBuilder, there might be instantiations in the type cache
13301          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
13302          * we want to return normal System.MonoType objects, so clear these out from the cache.
13303          *
13304          * Together with this we must ensure the contents of all instances to match the created type.
13305          */
13306         if (domain->type_hash && klass->generic_container) {
13307                 struct remove_instantiations_user_data data;
13308                 data.klass = klass;
13309                 data.error = &error;
13310                 mono_error_assert_ok (&error);
13311                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
13312                 if (!is_ok (&error))
13313                         goto failure;
13314         }
13315
13316         mono_domain_unlock (domain);
13317         mono_loader_unlock ();
13318
13319         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
13320                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13321                 mono_error_set_type_load_class (&error, klass, "Not a valid enumeration");
13322                 goto failure_unlocked;
13323         }
13324
13325         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
13326         if (!is_ok (&error))
13327                 goto failure_unlocked;
13328
13329         g_assert (res != (MonoReflectionType*)tb);
13330
13331         return res;
13332
13333 failure:
13334         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
13335         klass->wastypebuilder = TRUE;
13336         mono_domain_unlock (domain);
13337         mono_loader_unlock ();
13338 failure_unlocked:
13339         mono_error_set_pending_exception (&error);
13340         return NULL;
13341 }
13342
13343 static gboolean
13344 reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam, MonoError *error)
13345 {
13346         MonoGenericParamFull *param;
13347         MonoImage *image;
13348         MonoClass *pklass;
13349
13350         mono_error_init (error);
13351
13352         image = &gparam->tbuilder->module->dynamic_image->image;
13353
13354         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13355
13356         param->info.name = mono_string_to_utf8_image (image, gparam->name, error);
13357         mono_error_assert_ok (error);
13358         param->param.num = gparam->index;
13359
13360         if (gparam->mbuilder) {
13361                 if (!gparam->mbuilder->generic_container) {
13362                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, error);
13363                         return_val_if_nok (error, FALSE);
13364
13365                         MonoClass *klass = mono_class_from_mono_type (tb);
13366                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13367                         gparam->mbuilder->generic_container->is_method = TRUE;
13368                         /* 
13369                          * Cannot set owner.method, since the MonoMethod is not created yet.
13370                          * Set the image field instead, so type_in_image () works.
13371                          */
13372                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13373                         gparam->mbuilder->generic_container->owner.image = klass->image;
13374                 }
13375                 param->param.owner = gparam->mbuilder->generic_container;
13376         } else if (gparam->tbuilder) {
13377                 if (!gparam->tbuilder->generic_container) {
13378                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, error);
13379                         return_val_if_nok (error, FALSE);
13380                         MonoClass *klass = mono_class_from_mono_type (tb);
13381                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13382                         gparam->tbuilder->generic_container->owner.klass = klass;
13383                 }
13384                 param->param.owner = gparam->tbuilder->generic_container;
13385         }
13386
13387         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13388
13389         gparam->type.type = &pklass->byval_arg;
13390
13391         mono_class_set_ref_info (pklass, gparam);
13392         mono_image_append_class_to_reflection_info_set (pklass);
13393
13394         return TRUE;
13395 }
13396
13397 void
13398 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13399 {
13400         MonoError error;
13401         (void) reflection_initialize_generic_parameter (gparam, &error);
13402         mono_error_set_pending_exception (&error);
13403 }
13404
13405
13406 MonoArray *
13407 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13408 {
13409         MonoError error;
13410         MonoReflectionModuleBuilder *module = sig->module;
13411         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13412         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13413         guint32 buflen, i;
13414         MonoArray *result;
13415         SigBuffer buf;
13416
13417         check_array_for_usertypes (sig->arguments, &error);
13418         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13419
13420         sigbuffer_init (&buf, 32);
13421
13422         sigbuffer_add_value (&buf, 0x07);
13423         sigbuffer_add_value (&buf, na);
13424         if (assembly != NULL){
13425                 for (i = 0; i < na; ++i) {
13426                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13427                         encode_reflection_type (assembly, type, &buf, &error);
13428                         if (!is_ok (&error)) goto fail;
13429                 }
13430         }
13431
13432         buflen = buf.p - buf.buf;
13433         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13434         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13435         sigbuffer_free (&buf);
13436         return result;
13437 fail:
13438         sigbuffer_free (&buf);
13439         mono_error_raise_exception (&error); /* FIXME don't raise here */
13440         return NULL;
13441 }
13442
13443 MonoArray *
13444 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13445 {
13446         MonoError error;
13447         MonoDynamicImage *assembly = sig->module->dynamic_image;
13448         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13449         guint32 buflen, i;
13450         MonoArray *result;
13451         SigBuffer buf;
13452
13453         check_array_for_usertypes (sig->arguments, &error);
13454         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13455
13456         sigbuffer_init (&buf, 32);
13457
13458         sigbuffer_add_value (&buf, 0x06);
13459         for (i = 0; i < na; ++i) {
13460                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13461                 encode_reflection_type (assembly, type, &buf, &error);
13462                 if (!is_ok (&error))
13463                         goto fail;
13464         }
13465
13466         buflen = buf.p - buf.buf;
13467         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13468         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13469         sigbuffer_free (&buf);
13470
13471         return result;
13472 fail:
13473         sigbuffer_free (&buf);
13474         mono_error_raise_exception (&error); /* FIXME don't raise here */
13475         return NULL;
13476 }
13477
13478 typedef struct {
13479         MonoMethod *handle;
13480         MonoDomain *domain;
13481 } DynamicMethodReleaseData;
13482
13483 /*
13484  * The runtime automatically clean up those after finalization.
13485 */      
13486 static MonoReferenceQueue *dynamic_method_queue;
13487
13488 static void
13489 free_dynamic_method (void *dynamic_method)
13490 {
13491         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13492         MonoDomain *domain = data->domain;
13493         MonoMethod *method = data->handle;
13494         guint32 dis_link;
13495
13496         mono_domain_lock (domain);
13497         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13498         g_hash_table_remove (domain->method_to_dyn_method, method);
13499         mono_domain_unlock (domain);
13500         g_assert (dis_link);
13501         mono_gchandle_free (dis_link);
13502
13503         mono_runtime_free_method (domain, method);
13504         g_free (data);
13505 }
13506
13507 static gboolean
13508 reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb, MonoError *error)
13509 {
13510         MonoReferenceQueue *queue;
13511         MonoMethod *handle;
13512         DynamicMethodReleaseData *release_data;
13513         ReflectionMethodBuilder rmb;
13514         MonoMethodSignature *sig;
13515         MonoClass *klass;
13516         MonoDomain *domain;
13517         GSList *l;
13518         int i;
13519
13520         mono_error_init (error);
13521
13522         if (mono_runtime_is_shutting_down ()) {
13523                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
13524                 return FALSE;
13525         }
13526
13527         if (!(queue = dynamic_method_queue)) {
13528                 mono_loader_lock ();
13529                 if (!(queue = dynamic_method_queue))
13530                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13531                 mono_loader_unlock ();
13532         }
13533
13534         sig = dynamic_method_to_signature (mb, error);
13535         return_val_if_nok (error, FALSE);
13536
13537         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13538
13539         /*
13540          * Resolve references.
13541          */
13542         /* 
13543          * Every second entry in the refs array is reserved for storing handle_class,
13544          * which is needed by the ldtoken implementation in the JIT.
13545          */
13546         rmb.nrefs = mb->nrefs;
13547         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13548         for (i = 0; i < mb->nrefs; i += 2) {
13549                 MonoClass *handle_class;
13550                 gpointer ref;
13551                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13552
13553                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13554                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13555                         /*
13556                          * The referenced DynamicMethod should already be created by the managed
13557                          * code, except in the case of circular references. In that case, we store
13558                          * method in the refs array, and fix it up later when the referenced 
13559                          * DynamicMethod is created.
13560                          */
13561                         if (method->mhandle) {
13562                                 ref = method->mhandle;
13563                         } else {
13564                                 /* FIXME: GC object stored in unmanaged memory */
13565                                 ref = method;
13566
13567                                 /* FIXME: GC object stored in unmanaged memory */
13568                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13569                         }
13570                         handle_class = mono_defaults.methodhandle_class;
13571                 } else {
13572                         MonoException *ex = NULL;
13573                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL, error);
13574                         if (!is_ok  (error)) {
13575                                 g_free (rmb.refs);
13576                                 return FALSE;
13577                         }
13578                         if (!ref)
13579                                 ex = mono_get_exception_type_load (NULL, NULL);
13580                         else if (mono_security_core_clr_enabled ())
13581                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13582
13583                         if (ex) {
13584                                 g_free (rmb.refs);
13585                                 mono_error_set_exception_instance (error, ex);
13586                                 return FALSE;
13587                         }
13588                 }
13589
13590                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13591                 rmb.refs [i + 1] = handle_class;
13592         }               
13593
13594         if (mb->owner) {
13595                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
13596                 if (!is_ok (error)) {
13597                         g_free (rmb.refs);
13598                         return FALSE;
13599                 }
13600                 klass = mono_class_from_mono_type (owner_type);
13601         } else {
13602                 klass = mono_defaults.object_class;
13603         }
13604
13605         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13606         release_data = g_new (DynamicMethodReleaseData, 1);
13607         release_data->handle = handle;
13608         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13609         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13610                 g_free (release_data);
13611
13612         /* Fix up refs entries pointing at us */
13613         for (l = mb->referenced_by; l; l = l->next) {
13614                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13615                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13616                 gpointer *data;
13617                 
13618                 g_assert (method->mhandle);
13619
13620                 data = (gpointer*)wrapper->method_data;
13621                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13622                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13623                                 data [i + 1] = mb->mhandle;
13624                 }
13625         }
13626         g_slist_free (mb->referenced_by);
13627
13628         g_free (rmb.refs);
13629
13630         /* ilgen is no longer needed */
13631         mb->ilgen = NULL;
13632
13633         domain = mono_domain_get ();
13634         mono_domain_lock (domain);
13635         if (!domain->method_to_dyn_method)
13636                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13637         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13638         mono_domain_unlock (domain);
13639
13640         return TRUE;
13641 }
13642
13643 void
13644 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13645 {
13646         MonoError error;
13647         (void) reflection_create_dynamic_method (mb, &error);
13648         mono_error_set_pending_exception (&error);
13649 }
13650
13651 #endif /* DISABLE_REFLECTION_EMIT */
13652
13653 /**
13654  * 
13655  * mono_reflection_is_valid_dynamic_token:
13656  * 
13657  * Returns TRUE if token is valid.
13658  * 
13659  */
13660 gboolean
13661 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13662 {
13663         return lookup_dyn_token (image, token) != NULL;
13664 }
13665
13666 MonoMethodSignature *
13667 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13668 {
13669         MonoMethodSignature *sig;
13670         g_assert (image_is_dynamic (image));
13671
13672         mono_error_init (error);
13673
13674         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13675         if (sig)
13676                 return sig;
13677
13678         return mono_method_signature_checked (method, error);
13679 }
13680
13681 #ifndef DISABLE_REFLECTION_EMIT
13682
13683 /**
13684  * mono_reflection_lookup_dynamic_token:
13685  *
13686  * Finish the Builder object pointed to by TOKEN and return the corresponding
13687  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13688  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13689  * mapping table.
13690  *
13691  * LOCKING: Take the loader lock
13692  */
13693 gpointer
13694 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13695 {
13696         MonoError error;
13697         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13698         MonoObject *obj;
13699         MonoClass *klass;
13700
13701         obj = lookup_dyn_token (assembly, token);
13702         if (!obj) {
13703                 if (valid_token)
13704                         g_error ("Could not find required dynamic token 0x%08x", token);
13705                 else
13706                         return NULL;
13707         }
13708
13709         if (!handle_class)
13710                 handle_class = &klass;
13711         gpointer result = resolve_object (image, obj, handle_class, context, &error);
13712         mono_error_raise_exception (&error); /* FIXME don't raise here */
13713         return result;
13714 }
13715
13716 /*
13717  * ensure_complete_type:
13718  *
13719  *   Ensure that KLASS is completed if it is a dynamic type, or references
13720  * dynamic types.
13721  */
13722 static void
13723 ensure_complete_type (MonoClass *klass, MonoError *error)
13724 {
13725         mono_error_init (error);
13726
13727         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13728                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13729
13730                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13731                 return_if_nok (error);
13732
13733                 // Asserting here could break a lot of code
13734                 //g_assert (klass->wastypebuilder);
13735         }
13736
13737         if (klass->generic_class) {
13738                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13739                 int i;
13740
13741                 for (i = 0; i < inst->type_argc; ++i) {
13742                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
13743                         return_if_nok (error);
13744                 }
13745         }
13746 }
13747
13748 static gpointer
13749 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
13750 {
13751         gpointer result = NULL;
13752
13753         mono_error_init (error);
13754
13755         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13756                 result = mono_string_intern_checked ((MonoString*)obj, error);
13757                 return_val_if_nok (error, NULL);
13758                 *handle_class = mono_defaults.string_class;
13759                 g_assert (result);
13760         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13761                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13762                 return_val_if_nok (error, NULL);
13763                 MonoClass *mc = mono_class_from_mono_type (type);
13764                 if (!mono_class_init (mc)) {
13765                         mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (mc));
13766                         return NULL;
13767                 }
13768
13769                 if (context) {
13770                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
13771                         return_val_if_nok (error, NULL);
13772
13773                         result = mono_class_from_mono_type (inflated);
13774                         mono_metadata_free_type (inflated);
13775                 } else {
13776                         result = mono_class_from_mono_type (type);
13777                 }
13778                 *handle_class = mono_defaults.typehandle_class;
13779                 g_assert (result);
13780         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13781                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13782                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13783                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13784                 result = ((MonoReflectionMethod*)obj)->method;
13785                 if (context) {
13786                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13787                         mono_error_assert_ok (error);
13788                 }
13789                 *handle_class = mono_defaults.methodhandle_class;
13790                 g_assert (result);
13791         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13792                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13793                 result = mb->mhandle;
13794                 if (!result) {
13795                         /* Type is not yet created */
13796                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13797
13798                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13799                         return_val_if_nok (error, NULL);
13800
13801                         /*
13802                          * Hopefully this has been filled in by calling CreateType() on the
13803                          * TypeBuilder.
13804                          */
13805                         /*
13806                          * TODO: This won't work if the application finishes another 
13807                          * TypeBuilder instance instead of this one.
13808                          */
13809                         result = mb->mhandle;
13810                 }
13811                 if (context) {
13812                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13813                         mono_error_assert_ok (error);
13814                 }
13815                 *handle_class = mono_defaults.methodhandle_class;
13816         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13817                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13818
13819                 result = cb->mhandle;
13820                 if (!result) {
13821                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13822
13823                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13824                         return_val_if_nok (error, NULL);
13825                         result = cb->mhandle;
13826                 }
13827                 if (context) {
13828                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
13829                         mono_error_assert_ok (error);
13830                 }
13831                 *handle_class = mono_defaults.methodhandle_class;
13832         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13833                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13834
13835                 ensure_complete_type (field->parent, error);
13836                 return_val_if_nok (error, NULL);
13837
13838                 if (context) {
13839                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
13840                         return_val_if_nok (error, NULL);
13841
13842                         MonoClass *klass = mono_class_from_mono_type (inflated);
13843                         MonoClassField *inflated_field;
13844                         gpointer iter = NULL;
13845                         mono_metadata_free_type (inflated);
13846                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13847                                 if (!strcmp (field->name, inflated_field->name))
13848                                         break;
13849                         }
13850                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13851                         result = inflated_field;
13852                 } else {
13853                         result = field;
13854                 }
13855                 *handle_class = mono_defaults.fieldhandle_class;
13856                 g_assert (result);
13857         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13858                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13859                 result = fb->handle;
13860
13861                 if (!result) {
13862                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13863
13864                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13865                         return_val_if_nok (error, NULL);
13866                         result = fb->handle;
13867                 }
13868
13869                 if (fb->handle && fb->handle->parent->generic_container) {
13870                         MonoClass *klass = fb->handle->parent;
13871                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, error);
13872                         return_val_if_nok (error, NULL);
13873
13874                         MonoClass *inflated = mono_class_from_mono_type (type);
13875
13876                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13877                         g_assert (result);
13878                         mono_metadata_free_type (type);
13879                 }
13880                 *handle_class = mono_defaults.fieldhandle_class;
13881         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13882                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13883                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
13884                 return_val_if_nok (error, NULL);
13885                 MonoClass *klass;
13886
13887                 klass = type->data.klass;
13888                 if (klass->wastypebuilder) {
13889                         /* Already created */
13890                         result = klass;
13891                 }
13892                 else {
13893                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, error);
13894                         return_val_if_nok (error, NULL);
13895                         result = type->data.klass;
13896                         g_assert (result);
13897                 }
13898                 *handle_class = mono_defaults.typehandle_class;
13899         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13900                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13901                 MonoMethodSignature *sig;
13902                 int nargs, i;
13903
13904                 if (helper->arguments)
13905                         nargs = mono_array_length (helper->arguments);
13906                 else
13907                         nargs = 0;
13908
13909                 sig = mono_metadata_signature_alloc (image, nargs);
13910                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13911                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13912
13913                 if (helper->unmanaged_call_conv) { /* unmanaged */
13914                         sig->call_convention = helper->unmanaged_call_conv - 1;
13915                         sig->pinvoke = TRUE;
13916                 } else if (helper->call_conv & 0x02) {
13917                         sig->call_convention = MONO_CALL_VARARG;
13918                 } else {
13919                         sig->call_convention = MONO_CALL_DEFAULT;
13920                 }
13921
13922                 sig->param_count = nargs;
13923                 /* TODO: Copy type ? */
13924                 sig->ret = helper->return_type->type;
13925                 for (i = 0; i < nargs; ++i) {
13926                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, error);
13927                         if (!is_ok (error)) {
13928                                 image_g_free (image, sig);
13929                                 return NULL;
13930                         }
13931                 }
13932
13933                 result = sig;
13934                 *handle_class = NULL;
13935         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13936                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13937                 /* Already created by the managed code */
13938                 g_assert (method->mhandle);
13939                 result = method->mhandle;
13940                 *handle_class = mono_defaults.methodhandle_class;
13941         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13942                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13943                 return_val_if_nok (error, NULL);
13944                 type = mono_class_inflate_generic_type_checked (type, context, error);
13945                 return_val_if_nok (error, NULL);
13946
13947                 result = mono_class_from_mono_type (type);
13948                 *handle_class = mono_defaults.typehandle_class;
13949                 g_assert (result);
13950                 mono_metadata_free_type (type);
13951         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13952                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
13953                 return_val_if_nok (error, NULL);
13954                 type = mono_class_inflate_generic_type_checked (type, context, error);
13955                 return_val_if_nok (error, NULL);
13956
13957                 result = mono_class_from_mono_type (type);
13958                 *handle_class = mono_defaults.typehandle_class;
13959                 g_assert (result);
13960                 mono_metadata_free_type (type);
13961         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13962                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13963                 MonoClass *inflated;
13964                 MonoType *type;
13965                 MonoClassField *field;
13966
13967                 if (is_sre_field_builder (mono_object_class (f->fb)))
13968                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13969                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13970                         field = ((MonoReflectionField*)f->fb)->field;
13971                 else
13972                         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)));
13973
13974                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
13975                 return_val_if_nok (error, NULL);
13976                 type = mono_class_inflate_generic_type_checked (finst, context, error);
13977                 return_val_if_nok (error, NULL);
13978
13979                 inflated = mono_class_from_mono_type (type);
13980
13981                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13982                 ensure_complete_type (field->parent, error);
13983                 if (!is_ok (error)) {
13984                         mono_metadata_free_type (type);
13985                         return NULL;
13986                 }
13987
13988                 g_assert (result);
13989                 mono_metadata_free_type (type);
13990                 *handle_class = mono_defaults.fieldhandle_class;
13991         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13992                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13993                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
13994                 return_val_if_nok (error, NULL);
13995                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, error);
13996                 return_val_if_nok (error, NULL);
13997
13998                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13999                 MonoMethod *method;
14000
14001                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
14002                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
14003                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
14004                         method = ((MonoReflectionMethod *)c->cb)->method;
14005                 else
14006                         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)));
14007
14008                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
14009                 *handle_class = mono_defaults.methodhandle_class;
14010                 mono_metadata_free_type (type);
14011         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
14012                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
14013                 if (m->method_args) {
14014                         result = mono_reflection_method_on_tb_inst_get_handle (m, error);
14015                         return_val_if_nok (error, NULL);
14016                         if (context) {
14017                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
14018                                 mono_error_assert_ok (error);
14019                         }
14020                 } else {
14021                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
14022                         return_val_if_nok (error, NULL);
14023                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, error);
14024                         return_val_if_nok (error, NULL);
14025
14026                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
14027                         MonoMethod *method;
14028
14029                         if (is_sre_method_builder (mono_object_class (m->mb)))
14030                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
14031                         else if (is_sr_mono_method (mono_object_class (m->mb)))
14032                                 method = ((MonoReflectionMethod *)m->mb)->method;
14033                         else
14034                                 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)));
14035
14036                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
14037                         mono_metadata_free_type (type);
14038                 }
14039                 *handle_class = mono_defaults.methodhandle_class;
14040         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
14041                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
14042                 MonoType *mtype;
14043                 MonoClass *klass;
14044                 MonoMethod *method;
14045                 gpointer iter;
14046                 char *name;
14047
14048                 mtype = mono_reflection_type_get_handle (m->parent, error);
14049                 return_val_if_nok (error, NULL);
14050                 klass = mono_class_from_mono_type (mtype);
14051
14052                 /* Find the method */
14053
14054                 name = mono_string_to_utf8 (m->name);
14055                 iter = NULL;
14056                 while ((method = mono_class_get_methods (klass, &iter))) {
14057                         if (!strcmp (method->name, name))
14058                                 break;
14059                 }
14060                 g_free (name);
14061
14062                 // FIXME:
14063                 g_assert (method);
14064                 // FIXME: Check parameters/return value etc. match
14065
14066                 result = method;
14067                 *handle_class = mono_defaults.methodhandle_class;
14068         } else if (is_sre_array (mono_object_get_class(obj)) ||
14069                                 is_sre_byref (mono_object_get_class(obj)) ||
14070                                 is_sre_pointer (mono_object_get_class(obj))) {
14071                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
14072                 MonoType *type = mono_reflection_type_get_handle (ref_type, error);
14073                 return_val_if_nok (error, NULL);
14074
14075                 if (context) {
14076                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
14077                         return_val_if_nok (error, NULL);
14078
14079                         result = mono_class_from_mono_type (inflated);
14080                         mono_metadata_free_type (inflated);
14081                 } else {
14082                         result = mono_class_from_mono_type (type);
14083                 }
14084                 *handle_class = mono_defaults.typehandle_class;
14085         } else {
14086                 g_print ("%s\n", obj->vtable->klass->name);
14087                 g_assert_not_reached ();
14088         }
14089         return result;
14090 }
14091
14092 #else /* DISABLE_REFLECTION_EMIT */
14093
14094 MonoArray*
14095 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
14096 {
14097         g_assert_not_reached ();
14098         return NULL;
14099 }
14100
14101 void
14102 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
14103 {
14104         g_assert_not_reached ();
14105 }
14106
14107 void
14108 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
14109 {
14110         g_assert_not_reached ();
14111 }
14112
14113 void
14114 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
14115 {
14116         g_assert_not_reached ();
14117 }
14118
14119 void
14120 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
14121 {
14122         g_assert_not_reached ();
14123 }
14124
14125 void
14126 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
14127 {
14128         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
14129 }
14130
14131 void
14132 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
14133 {
14134         g_assert_not_reached ();
14135 }
14136
14137 void
14138 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
14139 {
14140         g_assert_not_reached ();
14141 }
14142
14143 MonoReflectionModule *
14144 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName, MonoError *error)
14145 {
14146         g_assert_not_reached ();
14147         return NULL;
14148 }
14149
14150 guint32
14151 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
14152 {
14153         g_assert_not_reached ();
14154         return 0;
14155 }
14156
14157 guint32
14158 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
14159 {
14160         g_assert_not_reached ();
14161         return 0;
14162 }
14163
14164 guint32
14165 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
14166                          gboolean create_open_instance, gboolean register_token, MonoError *error)
14167 {
14168         g_assert_not_reached ();
14169         return 0;
14170 }
14171
14172 void
14173 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
14174 {
14175 }
14176
14177 void
14178 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
14179 {
14180         g_assert_not_reached ();
14181 }
14182
14183 void
14184 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
14185 {
14186         mono_error_init (error);
14187         *overrides = NULL;
14188         *num_overrides = 0;
14189 }
14190
14191 MonoReflectionEvent *
14192 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
14193 {
14194         g_assert_not_reached ();
14195         return NULL;
14196 }
14197
14198 MonoReflectionType*
14199 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
14200 {
14201         g_assert_not_reached ();
14202         return NULL;
14203 }
14204
14205 void
14206 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
14207 {
14208         g_assert_not_reached ();
14209 }
14210
14211 MonoArray *
14212 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
14213 {
14214         g_assert_not_reached ();
14215         return NULL;
14216 }
14217
14218 MonoArray *
14219 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
14220 {
14221         g_assert_not_reached ();
14222         return NULL;
14223 }
14224
14225 void 
14226 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
14227 {
14228 }
14229
14230 gpointer
14231 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
14232 {
14233         return NULL;
14234 }
14235
14236 MonoType*
14237 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
14238 {
14239         mono_error_init (error);
14240         if (!ref)
14241                 return NULL;
14242         return ref->type;
14243 }
14244
14245 void
14246 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
14247 {
14248         g_assert_not_reached ();
14249 }
14250
14251 #endif /* DISABLE_REFLECTION_EMIT */
14252
14253 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
14254 const static guint32 declsec_flags_map[] = {
14255         0x00000000,                                     /* empty */
14256         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
14257         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
14258         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
14259         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
14260         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
14261         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
14262         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
14263         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
14264         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
14265         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
14266         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
14267         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
14268         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
14269         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
14270         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
14271         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
14272         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
14273         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
14274 };
14275
14276 /*
14277  * Returns flags that includes all available security action associated to the handle.
14278  * @token: metadata token (either for a class or a method)
14279  * @image: image where resides the metadata.
14280  */
14281 static guint32
14282 mono_declsec_get_flags (MonoImage *image, guint32 token)
14283 {
14284         int index = mono_metadata_declsec_from_index (image, token);
14285         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
14286         guint32 result = 0;
14287         guint32 action;
14288         int i;
14289
14290         /* HasSecurity can be present for other, not specially encoded, attributes,
14291            e.g. SuppressUnmanagedCodeSecurityAttribute */
14292         if (index < 0)
14293                 return 0;
14294
14295         for (i = index; i < t->rows; i++) {
14296                 guint32 cols [MONO_DECL_SECURITY_SIZE];
14297
14298                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14299                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14300                         break;
14301
14302                 action = cols [MONO_DECL_SECURITY_ACTION];
14303                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
14304                         result |= declsec_flags_map [action];
14305                 } else {
14306                         g_assert_not_reached ();
14307                 }
14308         }
14309         return result;
14310 }
14311
14312 /*
14313  * Get the security actions (in the form of flags) associated with the specified method.
14314  *
14315  * @method: The method for which we want the declarative security flags.
14316  * Return the declarative security flags for the method (only).
14317  *
14318  * Note: To keep MonoMethod size down we do not cache the declarative security flags
14319  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
14320  */
14321 guint32
14322 mono_declsec_flags_from_method (MonoMethod *method)
14323 {
14324         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14325                 /* FIXME: No cache (for the moment) */
14326                 guint32 idx = mono_method_get_index (method);
14327                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14328                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14329                 return mono_declsec_get_flags (method->klass->image, idx);
14330         }
14331         return 0;
14332 }
14333
14334 /*
14335  * Get the security actions (in the form of flags) associated with the specified class.
14336  *
14337  * @klass: The class for which we want the declarative security flags.
14338  * Return the declarative security flags for the class.
14339  *
14340  * Note: We cache the flags inside the MonoClass structure as this will get 
14341  *       called very often (at least for each method).
14342  */
14343 guint32
14344 mono_declsec_flags_from_class (MonoClass *klass)
14345 {
14346         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
14347                 if (!klass->ext || !klass->ext->declsec_flags) {
14348                         guint32 idx;
14349
14350                         idx = mono_metadata_token_index (klass->type_token);
14351                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14352                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14353                         mono_loader_lock ();
14354                         mono_class_alloc_ext (klass);
14355                         mono_loader_unlock ();
14356                         /* we cache the flags on classes */
14357                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
14358                 }
14359                 return klass->ext->declsec_flags;
14360         }
14361         return 0;
14362 }
14363
14364 /*
14365  * Get the security actions (in the form of flags) associated with the specified assembly.
14366  *
14367  * @assembly: The assembly for which we want the declarative security flags.
14368  * Return the declarative security flags for the assembly.
14369  */
14370 guint32
14371 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
14372 {
14373         guint32 idx = 1; /* there is only one assembly */
14374         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14375         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14376         return mono_declsec_get_flags (assembly->image, idx);
14377 }
14378
14379
14380 /*
14381  * Fill actions for the specific index (which may either be an encoded class token or
14382  * an encoded method token) from the metadata image.
14383  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
14384  */
14385 static MonoBoolean
14386 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
14387         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14388 {
14389         MonoBoolean result = FALSE;
14390         MonoTableInfo *t;
14391         guint32 cols [MONO_DECL_SECURITY_SIZE];
14392         int index = mono_metadata_declsec_from_index (image, token);
14393         int i;
14394
14395         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14396         for (i = index; i < t->rows; i++) {
14397                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14398
14399                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14400                         return result;
14401
14402                 /* if present only replace (class) permissions with method permissions */
14403                 /* if empty accept either class or method permissions */
14404                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14405                         if (!actions->demand.blob) {
14406                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14407                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14408                                 actions->demand.blob = (char*) (blob + 2);
14409                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14410                                 result = TRUE;
14411                         }
14412                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14413                         if (!actions->noncasdemand.blob) {
14414                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14415                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14416                                 actions->noncasdemand.blob = (char*) (blob + 2);
14417                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14418                                 result = TRUE;
14419                         }
14420                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14421                         if (!actions->demandchoice.blob) {
14422                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14423                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14424                                 actions->demandchoice.blob = (char*) (blob + 2);
14425                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14426                                 result = TRUE;
14427                         }
14428                 }
14429         }
14430
14431         return result;
14432 }
14433
14434 static MonoBoolean
14435 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14436         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14437 {
14438         guint32 idx = mono_metadata_token_index (klass->type_token);
14439         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14440         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14441         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14442 }
14443
14444 static MonoBoolean
14445 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14446         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14447 {
14448         guint32 idx = mono_method_get_index (method);
14449         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14450         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14451         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14452 }
14453
14454 /*
14455  * Collect all actions (that requires to generate code in mini) assigned for
14456  * the specified method.
14457  * Note: Don't use the content of actions if the function return FALSE.
14458  */
14459 MonoBoolean
14460 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14461 {
14462         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14463                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14464         MonoBoolean result = FALSE;
14465         guint32 flags;
14466
14467         /* quick exit if no declarative security is present in the metadata */
14468         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14469                 return FALSE;
14470
14471         /* we want the original as the wrapper is "free" of the security informations */
14472         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14473                 method = mono_marshal_method_from_wrapper (method);
14474                 if (!method)
14475                         return FALSE;
14476         }
14477
14478         /* First we look for method-level attributes */
14479         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14480                 mono_class_init (method->klass);
14481                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14482
14483                 result = mono_declsec_get_method_demands_params (method, demands, 
14484                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14485         }
14486
14487         /* Here we use (or create) the class declarative cache to look for demands */
14488         flags = mono_declsec_flags_from_class (method->klass);
14489         if (flags & mask) {
14490                 if (!result) {
14491                         mono_class_init (method->klass);
14492                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14493                 }
14494                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14495                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14496         }
14497
14498         /* The boolean return value is used as a shortcut in case nothing needs to
14499            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14500         return result;
14501 }
14502
14503
14504 /*
14505  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14506  *
14507  * Note: Don't use the content of actions if the function return FALSE.
14508  */
14509 MonoBoolean
14510 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14511 {
14512         MonoBoolean result = FALSE;
14513         guint32 flags;
14514
14515         /* quick exit if no declarative security is present in the metadata */
14516         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14517                 return FALSE;
14518
14519         /* we want the original as the wrapper is "free" of the security informations */
14520         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14521                 method = mono_marshal_method_from_wrapper (method);
14522                 if (!method)
14523                         return FALSE;
14524         }
14525
14526         /* results are independant - zeroize both */
14527         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14528         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14529
14530         /* First we look for method-level attributes */
14531         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14532                 mono_class_init (method->klass);
14533
14534                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14535                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14536         }
14537
14538         /* Here we use (or create) the class declarative cache to look for demands */
14539         flags = mono_declsec_flags_from_class (method->klass);
14540         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14541                 mono_class_init (method->klass);
14542
14543                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14544                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14545         }
14546
14547         return result;
14548 }
14549
14550 /*
14551  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14552  *
14553  * @klass       The inherited class - this is the class that provides the security check (attributes)
14554  * @demans      
14555  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14556  * 
14557  * Note: Don't use the content of actions if the function return FALSE.
14558  */
14559 MonoBoolean
14560 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14561 {
14562         MonoBoolean result = FALSE;
14563         guint32 flags;
14564
14565         /* quick exit if no declarative security is present in the metadata */
14566         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14567                 return FALSE;
14568
14569         /* Here we use (or create) the class declarative cache to look for demands */
14570         flags = mono_declsec_flags_from_class (klass);
14571         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14572                 mono_class_init (klass);
14573                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14574
14575                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14576                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14577         }
14578
14579         return result;
14580 }
14581
14582 /*
14583  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14584  *
14585  * Note: Don't use the content of actions if the function return FALSE.
14586  */
14587 MonoBoolean
14588 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14589 {
14590         /* quick exit if no declarative security is present in the metadata */
14591         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14592                 return FALSE;
14593
14594         /* we want the original as the wrapper is "free" of the security informations */
14595         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14596                 method = mono_marshal_method_from_wrapper (method);
14597                 if (!method)
14598                         return FALSE;
14599         }
14600
14601         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14602                 mono_class_init (method->klass);
14603                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14604
14605                 return mono_declsec_get_method_demands_params (method, demands, 
14606                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14607         }
14608         return FALSE;
14609 }
14610
14611
14612 static MonoBoolean
14613 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14614 {
14615         guint32 cols [MONO_DECL_SECURITY_SIZE];
14616         MonoTableInfo *t;
14617         int i;
14618
14619         int index = mono_metadata_declsec_from_index (image, token);
14620         if (index == -1)
14621                 return FALSE;
14622
14623         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14624         for (i = index; i < t->rows; i++) {
14625                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14626
14627                 /* shortcut - index are ordered */
14628                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14629                         return FALSE;
14630
14631                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14632                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14633                         entry->blob = (char*) (metadata + 2);
14634                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14635                         return TRUE;
14636                 }
14637         }
14638
14639         return FALSE;
14640 }
14641
14642 MonoBoolean
14643 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14644 {
14645         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14646                 guint32 idx = mono_method_get_index (method);
14647                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14648                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14649                 return get_declsec_action (method->klass->image, idx, action, entry);
14650         }
14651         return FALSE;
14652 }
14653
14654 MonoBoolean
14655 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14656 {
14657         /* use cache */
14658         guint32 flags = mono_declsec_flags_from_class (klass);
14659         if (declsec_flags_map [action] & flags) {
14660                 guint32 idx = mono_metadata_token_index (klass->type_token);
14661                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14662                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14663                 return get_declsec_action (klass->image, idx, action, entry);
14664         }
14665         return FALSE;
14666 }
14667
14668 MonoBoolean
14669 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14670 {
14671         guint32 idx = 1; /* there is only one assembly */
14672         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14673         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14674
14675         return get_declsec_action (assembly->image, idx, action, entry);
14676 }
14677
14678 gboolean
14679 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass, MonoError *error)
14680 {
14681         MonoObject *res, *exc;
14682         void *params [1];
14683         static MonoMethod *method = NULL;
14684
14685         mono_error_init (error);
14686
14687         if (method == NULL) {
14688                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14689                 g_assert (method);
14690         }
14691
14692         /* 
14693          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14694          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14695          */
14696         g_assert (mono_class_get_ref_info (klass));
14697         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14698
14699         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, error);
14700         return_val_if_nok (error, FALSE);
14701
14702         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, error);
14703
14704         if (exc || !mono_error_ok (error)) {
14705                 mono_error_cleanup (error);
14706                 return FALSE;
14707         } else
14708                 return *(MonoBoolean*)mono_object_unbox (res);
14709 }
14710
14711 /**
14712  * mono_reflection_type_get_type:
14713  * @reftype: the System.Type object
14714  *
14715  * Returns the MonoType* associated with the C# System.Type object @reftype.
14716  */
14717 MonoType*
14718 mono_reflection_type_get_type (MonoReflectionType *reftype)
14719 {
14720         g_assert (reftype);
14721
14722         MonoError error;
14723         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14724         mono_error_assert_ok (&error);
14725         return result;
14726 }
14727
14728 /**
14729  * mono_reflection_assembly_get_assembly:
14730  * @refassembly: the System.Reflection.Assembly object
14731  *
14732  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14733  */
14734 MonoAssembly*
14735 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14736 {
14737         g_assert (refassembly);
14738
14739         return refassembly->assembly;
14740 }
14741