6235fd849bf645ca1ef13346a48a3c002d2b12b4
[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);
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);
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 guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 /**
428  * image_g_free:
429  * @image: a MonoImage
430  * @ptr: pointer
431  *
432  * If @image is NULL, free @ptr, otherwise do nothing.
433  */
434 static void
435 image_g_free (MonoImage *image, gpointer ptr)
436 {
437         if (image == NULL)
438                 g_free (ptr);
439 }
440
441 #ifndef DISABLE_REFLECTION_EMIT
442 static char*
443 image_strdup (MonoImage *image, const char *s)
444 {
445         MONO_REQ_GC_NEUTRAL_MODE;
446
447         if (image)
448                 return mono_image_strdup (image, s);
449         else
450                 return g_strdup (s);
451 }
452 #endif
453
454 #define image_g_new(image,struct_type, n_structs)               \
455     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
456
457 #define image_g_new0(image,struct_type, n_structs)              \
458     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460
461 static void
462 alloc_table (MonoDynamicTable *table, guint nrows)
463 {
464         MONO_REQ_GC_NEUTRAL_MODE;
465
466         table->rows = nrows;
467         g_assert (table->columns);
468         if (nrows + 1 >= table->alloc_rows) {
469                 while (nrows + 1 >= table->alloc_rows) {
470                         if (table->alloc_rows == 0)
471                                 table->alloc_rows = 16;
472                         else
473                                 table->alloc_rows *= 2;
474                 }
475
476                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
477         }
478 }
479
480 static void
481 make_room_in_stream (MonoDynamicStream *stream, int size)
482 {
483         MONO_REQ_GC_NEUTRAL_MODE;
484
485         if (size <= stream->alloc_size)
486                 return;
487         
488         while (stream->alloc_size <= size) {
489                 if (stream->alloc_size < 4096)
490                         stream->alloc_size = 4096;
491                 else
492                         stream->alloc_size *= 2;
493         }
494         
495         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
496 }
497
498 static guint32
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
500 {
501         MONO_REQ_GC_NEUTRAL_MODE;
502
503         guint32 idx;
504         guint32 len;
505         gpointer oldkey, oldval;
506
507         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508                 return GPOINTER_TO_UINT (oldval);
509
510         len = strlen (str) + 1;
511         idx = sh->index;
512         
513         make_room_in_stream (sh, idx + len);
514
515         /*
516          * We strdup the string even if we already copy them in sh->data
517          * so that the string pointers in the hash remain valid even if
518          * we need to realloc sh->data. We may want to avoid that later.
519          */
520         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521         memcpy (sh->data + idx, str, len);
522         sh->index += len;
523         return idx;
524 }
525
526 static guint32
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
528 {
529         MONO_REQ_GC_UNSAFE_MODE;
530
531         char *name = mono_string_to_utf8 (str);
532         guint32 idx;
533         idx = string_heap_insert (sh, name);
534         g_free (name);
535         return idx;
536 }
537
538 #ifndef DISABLE_REFLECTION_EMIT
539 static void
540 string_heap_init (MonoDynamicStream *sh)
541 {
542         MONO_REQ_GC_NEUTRAL_MODE;
543
544         sh->index = 0;
545         sh->alloc_size = 4096;
546         sh->data = (char *)g_malloc (4096);
547         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548         string_heap_insert (sh, "");
549 }
550 #endif
551
552 static guint32
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
554 {
555         MONO_REQ_GC_NEUTRAL_MODE;
556
557         guint32 idx;
558         
559         make_room_in_stream (stream, stream->index + len);
560         memcpy (stream->data + stream->index, data, len);
561         idx = stream->index;
562         stream->index += len;
563         /* 
564          * align index? Not without adding an additional param that controls it since
565          * we may store a blob value in pieces.
566          */
567         return idx;
568 }
569
570 static guint32
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         guint32 idx;
576         
577         make_room_in_stream (stream, stream->index + len);
578         memset (stream->data + stream->index, 0, len);
579         idx = stream->index;
580         stream->index += len;
581         return idx;
582 }
583
584 static void
585 stream_data_align (MonoDynamicStream *stream)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         char buf [4] = {0};
590         guint32 count = stream->index % 4;
591
592         /* we assume the stream data will be aligned */
593         if (count)
594                 mono_image_add_stream_data (stream, buf, 4 - count);
595 }
596
597 #ifndef DISABLE_REFLECTION_EMIT
598 static int
599 mono_blob_entry_hash (const char* str)
600 {
601         MONO_REQ_GC_NEUTRAL_MODE;
602
603         guint len, h;
604         const char *end;
605         len = mono_metadata_decode_blob_size (str, &str);
606         if (len > 0) {
607                 end = str + len;
608                 h = *str;
609                 for (str += 1; str < end; str++)
610                         h = (h << 5) - h + *str;
611                 return h;
612         } else {
613                 return 0;
614         }
615 }
616
617 static gboolean
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619         MONO_REQ_GC_NEUTRAL_MODE;
620
621         int len, len2;
622         const char *end1;
623         const char *end2;
624         len = mono_metadata_decode_blob_size (str1, &end1);
625         len2 = mono_metadata_decode_blob_size (str2, &end2);
626         if (len != len2)
627                 return 0;
628         return memcmp (end1, end2, len) == 0;
629 }
630 #endif
631 static guint32
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
633 {
634         MONO_REQ_GC_NEUTRAL_MODE;
635
636         guint32 idx;
637         char *copy;
638         gpointer oldkey, oldval;
639
640         copy = (char *)g_malloc (s1+s2);
641         memcpy (copy, b1, s1);
642         memcpy (copy + s1, b2, s2);
643         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
644                 g_free (copy);
645                 idx = GPOINTER_TO_UINT (oldval);
646         } else {
647                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648                 mono_image_add_stream_data (&assembly->blob, b2, s2);
649                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
650         }
651         return idx;
652 }
653
654 static guint32
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
656 {
657         MONO_REQ_GC_NEUTRAL_MODE;
658
659         char blob_size [8];
660         char *b = blob_size;
661         guint32 size = buf->p - buf->buf;
662         /* store length */
663         g_assert (size <= (buf->end - buf->buf));
664         mono_metadata_encode_value (size, b, &b);
665         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
666 }
667
668 /*
669  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670  * dest may be misaligned.
671  */
672 static void
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674         MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
676         int elem;
677
678         for (elem = 0; elem < nelem; ++elem) {
679                 switch (len) {
680                 case 1:
681                         *dest = *val;
682                         break;
683                 case 2:
684                         dest [0] = val [1];
685                         dest [1] = val [0];
686                         break;
687                 case 4:
688                         dest [0] = val [3];
689                         dest [1] = val [2];
690                         dest [2] = val [1];
691                         dest [3] = val [0];
692                         break;
693                 case 8:
694                         dest [0] = val [7];
695                         dest [1] = val [6];
696                         dest [2] = val [5];
697                         dest [3] = val [4];
698                         dest [4] = val [3];
699                         dest [5] = val [2];
700                         dest [6] = val [1];
701                         dest [7] = val [0];
702                         break;
703                 default:
704                         g_assert_not_reached ();
705                 }
706                 dest += len;
707                 val += len;
708         }
709 #else
710         memcpy (dest, val, len * nelem);
711 #endif
712 }
713
714 static guint32
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718         
719         char blob_size [64];
720         char *b = blob_size;
721         guint32 idx = 0, len;
722
723         len = str->length * 2;
724         mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
726         {
727                 char *swapped = g_malloc (2 * mono_string_length (str));
728                 const char *p = (const char*)mono_string_chars (str);
729
730                 swap_with_size (swapped, p, 2, mono_string_length (str));
731                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
732                 g_free (swapped);
733         }
734 #else
735         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
736 #endif
737         return idx;
738 }
739
740 #ifndef DISABLE_REFLECTION_EMIT
741 static MonoClass *
742 default_class_from_mono_type (MonoType *type)
743 {
744         MONO_REQ_GC_NEUTRAL_MODE;
745
746         switch (type->type) {
747         case MONO_TYPE_OBJECT:
748                 return mono_defaults.object_class;
749         case MONO_TYPE_VOID:
750                 return mono_defaults.void_class;
751         case MONO_TYPE_BOOLEAN:
752                 return mono_defaults.boolean_class;
753         case MONO_TYPE_CHAR:
754                 return mono_defaults.char_class;
755         case MONO_TYPE_I1:
756                 return mono_defaults.sbyte_class;
757         case MONO_TYPE_U1:
758                 return mono_defaults.byte_class;
759         case MONO_TYPE_I2:
760                 return mono_defaults.int16_class;
761         case MONO_TYPE_U2:
762                 return mono_defaults.uint16_class;
763         case MONO_TYPE_I4:
764                 return mono_defaults.int32_class;
765         case MONO_TYPE_U4:
766                 return mono_defaults.uint32_class;
767         case MONO_TYPE_I:
768                 return mono_defaults.int_class;
769         case MONO_TYPE_U:
770                 return mono_defaults.uint_class;
771         case MONO_TYPE_I8:
772                 return mono_defaults.int64_class;
773         case MONO_TYPE_U8:
774                 return mono_defaults.uint64_class;
775         case MONO_TYPE_R4:
776                 return mono_defaults.single_class;
777         case MONO_TYPE_R8:
778                 return mono_defaults.double_class;
779         case MONO_TYPE_STRING:
780                 return mono_defaults.string_class;
781         default:
782                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783                 g_assert_not_reached ();
784         }
785         
786         return NULL;
787 }
788 #endif
789
790 /*
791  * mono_class_get_ref_info:
792  *
793  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
794  */
795 gpointer
796 mono_class_get_ref_info (MonoClass *klass)
797 {
798         MONO_REQ_GC_UNSAFE_MODE;
799
800         if (klass->ref_info_handle == 0)
801                 return NULL;
802         else
803                 return mono_gchandle_get_target (klass->ref_info_handle);
804 }
805
806 void
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
808 {
809         MONO_REQ_GC_UNSAFE_MODE;
810
811         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812         g_assert (klass->ref_info_handle != 0);
813 }
814
815 void
816 mono_class_free_ref_info (MonoClass *klass)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (klass->ref_info_handle) {
821                 mono_gchandle_free (klass->ref_info_handle);
822                 klass->ref_info_handle = 0;
823         }
824 }
825
826 static void
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
828 {
829         MONO_REQ_GC_NEUTRAL_MODE;
830
831         int i;
832         MonoGenericInst *class_inst;
833         MonoClass *klass;
834
835         g_assert (gclass);
836
837         class_inst = gclass->context.class_inst;
838
839         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840         klass = gclass->container_class;
841         sigbuffer_add_value (buf, klass->byval_arg.type);
842         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
843
844         sigbuffer_add_value (buf, class_inst->type_argc);
845         for (i = 0; i < class_inst->type_argc; ++i)
846                 encode_type (assembly, class_inst->type_argv [i], buf);
847
848 }
849
850 static void
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
852 {
853         MONO_REQ_GC_NEUTRAL_MODE;
854
855         if (!type) {
856                 g_assert_not_reached ();
857                 return;
858         }
859                 
860         if (type->byref)
861                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
862
863         switch (type->type){
864         case MONO_TYPE_VOID:
865         case MONO_TYPE_BOOLEAN:
866         case MONO_TYPE_CHAR:
867         case MONO_TYPE_I1:
868         case MONO_TYPE_U1:
869         case MONO_TYPE_I2:
870         case MONO_TYPE_U2:
871         case MONO_TYPE_I4:
872         case MONO_TYPE_U4:
873         case MONO_TYPE_I8:
874         case MONO_TYPE_U8:
875         case MONO_TYPE_R4:
876         case MONO_TYPE_R8:
877         case MONO_TYPE_I:
878         case MONO_TYPE_U:
879         case MONO_TYPE_STRING:
880         case MONO_TYPE_OBJECT:
881         case MONO_TYPE_TYPEDBYREF:
882                 sigbuffer_add_value (buf, type->type);
883                 break;
884         case MONO_TYPE_PTR:
885                 sigbuffer_add_value (buf, type->type);
886                 encode_type (assembly, type->data.type, buf);
887                 break;
888         case MONO_TYPE_SZARRAY:
889                 sigbuffer_add_value (buf, type->type);
890                 encode_type (assembly, &type->data.klass->byval_arg, buf);
891                 break;
892         case MONO_TYPE_VALUETYPE:
893         case MONO_TYPE_CLASS: {
894                 MonoClass *k = mono_class_from_mono_type (type);
895
896                 if (k->generic_container) {
897                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898                         encode_generic_class (assembly, gclass, buf);
899                 } else {
900                         /*
901                          * Make sure we use the correct type.
902                          */
903                         sigbuffer_add_value (buf, k->byval_arg.type);
904                         /*
905                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906                          * otherwise two typerefs could point to the same type, leading to
907                          * verification errors.
908                          */
909                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
910                 }
911                 break;
912         }
913         case MONO_TYPE_ARRAY:
914                 sigbuffer_add_value (buf, type->type);
915                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916                 sigbuffer_add_value (buf, type->data.array->rank);
917                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918                 sigbuffer_add_value (buf, 0);
919                 break;
920         case MONO_TYPE_GENERICINST:
921                 encode_generic_class (assembly, type->data.generic_class, buf);
922                 break;
923         case MONO_TYPE_VAR:
924         case MONO_TYPE_MVAR:
925                 sigbuffer_add_value (buf, type->type);
926                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
927                 break;
928         default:
929                 g_error ("need to encode type %x", type->type);
930         }
931 }
932
933 static void
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
935 {
936         MONO_REQ_GC_UNSAFE_MODE;
937
938         mono_error_init (error);
939
940         if (!type) {
941                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
942                 return;
943         }
944
945         MonoType *t = mono_reflection_type_get_handle (type, error);
946         return_if_nok (error);
947         encode_type (assembly, t, buf);
948 }
949
950 static void
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
952 {
953         MONO_REQ_GC_UNSAFE_MODE;
954
955         int i;
956
957         mono_error_init (error);
958
959         if (modreq) {
960                 for (i = 0; i < mono_array_length (modreq); ++i) {
961                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962                         return_if_nok (error);
963                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
965                 }
966         }
967         if (modopt) {
968                 for (i = 0; i < mono_array_length (modopt); ++i) {
969                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970                         return_if_nok (error);
971                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973                 }
974         }
975 }
976
977 #ifndef DISABLE_REFLECTION_EMIT
978 static guint32
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
980 {
981         MONO_REQ_GC_UNSAFE_MODE;
982
983         SigBuffer buf;
984         int i;
985         guint32 nparams =  sig->param_count;
986         guint32 idx;
987
988         if (!assembly->save)
989                 return 0;
990
991         sigbuffer_init (&buf, 32);
992         /*
993          * FIXME: vararg, explicit_this, differenc call_conv values...
994          */
995         idx = sig->call_convention;
996         if (sig->hasthis)
997                 idx |= 0x20; /* hasthis */
998         if (sig->generic_param_count)
999                 idx |= 0x10; /* generic */
1000         sigbuffer_add_byte (&buf, idx);
1001         if (sig->generic_param_count)
1002                 sigbuffer_add_value (&buf, sig->generic_param_count);
1003         sigbuffer_add_value (&buf, nparams);
1004         encode_type (assembly, sig->ret, &buf);
1005         for (i = 0; i < nparams; ++i) {
1006                 if (i == sig->sentinelpos)
1007                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008                 encode_type (assembly, sig->params [i], &buf);
1009         }
1010         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011         sigbuffer_free (&buf);
1012         return idx;
1013 }
1014 #endif
1015
1016 static guint32
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1018 {
1019         MONO_REQ_GC_UNSAFE_MODE;
1020
1021         mono_error_init (error);
1022
1023         /*
1024          * FIXME: reuse code from method_encode_signature().
1025          */
1026         SigBuffer buf;
1027         int i;
1028         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1029         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1031         guint32 idx;
1032
1033         sigbuffer_init (&buf, 32);
1034         /* LAMESPEC: all the call conv spec is foobared */
1035         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036         if (mb->call_conv & 2)
1037                 idx |= 0x5; /* vararg */
1038         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039                 idx |= 0x20; /* hasthis */
1040         if (ngparams)
1041                 idx |= 0x10; /* generic */
1042         sigbuffer_add_byte (&buf, idx);
1043         if (ngparams)
1044                 sigbuffer_add_value (&buf, ngparams);
1045         sigbuffer_add_value (&buf, nparams + notypes);
1046         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1047         if (!is_ok (error))
1048                 goto leave;
1049         encode_reflection_type (assembly, mb->rtype, &buf, error);
1050         if (!is_ok (error))
1051                 goto leave;
1052         for (i = 0; i < nparams; ++i) {
1053                 MonoArray *modreq = NULL;
1054                 MonoArray *modopt = NULL;
1055                 MonoReflectionType *pt;
1056
1057                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1062                 if (!is_ok (error))
1063                         goto leave;
1064                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065                 encode_reflection_type (assembly, pt, &buf, error);
1066                 if (!is_ok (error))
1067                         goto leave;
1068         }
1069         if (notypes)
1070                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071         for (i = 0; i < notypes; ++i) {
1072                 MonoReflectionType *pt;
1073
1074                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075                 encode_reflection_type (assembly, pt, &buf, error);
1076                 if (!is_ok (error))
1077                         goto leave;
1078         }
1079
1080         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1081 leave:
1082         sigbuffer_free (&buf);
1083         return idx;
1084 }
1085
1086 static guint32
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1088 {
1089         MONO_REQ_GC_UNSAFE_MODE;
1090
1091         mono_error_init (error);
1092
1093         MonoDynamicTable *table;
1094         guint32 *values;
1095         guint32 idx, sig_idx;
1096         guint nl = mono_array_length (ilgen->locals);
1097         SigBuffer buf;
1098         int i;
1099
1100         sigbuffer_init (&buf, 32);
1101         sigbuffer_add_value (&buf, 0x07);
1102         sigbuffer_add_value (&buf, nl);
1103         for (i = 0; i < nl; ++i) {
1104                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1105                 
1106                 if (lb->is_pinned)
1107                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1108                 
1109                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110                 if (!is_ok (error)) {
1111                         sigbuffer_free (&buf);
1112                         return 0;
1113                 }
1114         }
1115         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116         sigbuffer_free (&buf);
1117
1118         if (assembly->standalonesig_cache == NULL)
1119                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1121         if (idx)
1122                 return idx;
1123
1124         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125         idx = table->next_idx ++;
1126         table->rows ++;
1127         alloc_table (table, table->rows);
1128         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1129
1130         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1131
1132         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1133
1134         return idx;
1135 }
1136
1137 static guint32
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1139 {
1140         MONO_REQ_GC_UNSAFE_MODE;
1141
1142         guint32 num_clauses = 0;
1143         int i;
1144
1145         MonoILExceptionInfo *ex_info;
1146         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148                 if (ex_info->handlers)
1149                         num_clauses += mono_array_length (ex_info->handlers);
1150                 else
1151                         num_clauses++;
1152         }
1153
1154         return num_clauses;
1155 }
1156
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1160 {
1161         MONO_REQ_GC_UNSAFE_MODE;
1162
1163         mono_error_init (error);
1164
1165         MonoExceptionClause *clauses;
1166         MonoExceptionClause *clause;
1167         MonoILExceptionInfo *ex_info;
1168         MonoILExceptionBlock *ex_block;
1169         guint32 finally_start;
1170         int i, j, clause_index;;
1171
1172         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1173
1174         clause_index = 0;
1175         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177                 finally_start = ex_info->start + ex_info->len;
1178                 if (!ex_info->handlers)
1179                         continue;
1180                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182                         clause = &(clauses [clause_index]);
1183
1184                         clause->flags = ex_block->type;
1185                         clause->try_offset = ex_info->start;
1186
1187                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188                                 clause->try_len = finally_start - ex_info->start;
1189                         else
1190                                 clause->try_len = ex_info->len;
1191                         clause->handler_offset = ex_block->start;
1192                         clause->handler_len = ex_block->len;
1193                         if (ex_block->extype) {
1194                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1195
1196                                 if (!is_ok (error)) {
1197                                         image_g_free (image, clauses);
1198                                         return NULL;
1199                                 }
1200                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1201                         } else {
1202                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203                                         clause->data.filter_offset = ex_block->filter_offset;
1204                                 else
1205                                         clause->data.filter_offset = 0;
1206                         }
1207                         finally_start = ex_block->start + ex_block->len;
1208
1209                         clause_index ++;
1210                 }
1211         }
1212
1213         return clauses;
1214 }
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1216
1217 /**
1218  * method_encode_code:
1219  *
1220  * @assembly the assembly
1221  * @mb the managed MethodBuilder
1222  * @error set on error
1223  *
1224  * Note that the return value is not sensible if @error is set.
1225  */
1226 static guint32
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1228 {
1229         MONO_REQ_GC_UNSAFE_MODE;
1230
1231         char flags = 0;
1232         guint32 idx;
1233         guint32 code_size;
1234         gint32 max_stack, i;
1235         gint32 num_locals = 0;
1236         gint32 num_exception = 0;
1237         gint maybe_small;
1238         guint32 fat_flags;
1239         char fat_header [12];
1240         guint32 int_value;
1241         guint16 short_value;
1242         guint32 local_sig = 0;
1243         guint32 header_size = 12;
1244         MonoArray *code;
1245
1246         mono_error_init (error);
1247
1248         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1250                 return 0;
1251
1252         /*if (mb->name)
1253                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1254         if (mb->ilgen) {
1255                 code = mb->ilgen->code;
1256                 code_size = mb->ilgen->code_len;
1257                 max_stack = mb->ilgen->max_stack;
1258                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259                 if (mb->ilgen->ex_handlers)
1260                         num_exception = method_count_clauses (mb->ilgen);
1261         } else {
1262                 code = mb->code;
1263                 if (code == NULL){
1264                         char *name = mono_string_to_utf8 (mb->name);
1265                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1267                         g_free (str);
1268                         g_free (name);
1269                         return 0;
1270                 }
1271
1272                 code_size = mono_array_length (code);
1273                 max_stack = 8; /* we probably need to run a verifier on the code... */
1274         }
1275
1276         stream_data_align (&assembly->code);
1277
1278         /* check for exceptions, maxstack, locals */
1279         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1280         if (maybe_small) {
1281                 if (code_size < 64 && !(code_size & 1)) {
1282                         flags = (code_size << 2) | 0x2;
1283                 } else if (code_size < 32 && (code_size & 1)) {
1284                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1285                 } else {
1286                         goto fat_header;
1287                 }
1288                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289                 /* add to the fixup todo list */
1290                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293                 return assembly->text_rva + idx;
1294         } 
1295 fat_header:
1296         if (num_locals) {
1297                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298                 return_val_if_nok (error, 0);
1299         }
1300         /* 
1301          * FIXME: need to set also the header size in fat_flags.
1302          * (and more sects and init locals flags)
1303          */
1304         fat_flags =  0x03;
1305         if (num_exception)
1306                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307         if (mb->init_locals)
1308                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309         fat_header [0] = fat_flags;
1310         fat_header [1] = (header_size / 4 ) << 4;
1311         short_value = GUINT16_TO_LE (max_stack);
1312         memcpy (fat_header + 2, &short_value, 2);
1313         int_value = GUINT32_TO_LE (code_size);
1314         memcpy (fat_header + 4, &int_value, 4);
1315         int_value = GUINT32_TO_LE (local_sig);
1316         memcpy (fat_header + 8, &int_value, 4);
1317         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318         /* add to the fixup todo list */
1319         if (mb->ilgen && mb->ilgen->num_token_fixups)
1320                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1321         
1322         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323         if (num_exception) {
1324                 unsigned char sheader [4];
1325                 MonoILExceptionInfo * ex_info;
1326                 MonoILExceptionBlock * ex_block;
1327                 int j;
1328
1329                 stream_data_align (&assembly->code);
1330                 /* always use fat format for now */
1331                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332                 num_exception *= 6 * sizeof (guint32);
1333                 num_exception += 4; /* include the size of the header */
1334                 sheader [1] = num_exception & 0xff;
1335                 sheader [2] = (num_exception >> 8) & 0xff;
1336                 sheader [3] = (num_exception >> 16) & 0xff;
1337                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338                 /* fat header, so we are already aligned */
1339                 /* reverse order */
1340                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342                         if (ex_info->handlers) {
1343                                 int finally_start = ex_info->start + ex_info->len;
1344                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1345                                         guint32 val;
1346                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1347                                         /* the flags */
1348                                         val = GUINT32_TO_LE (ex_block->type);
1349                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1350                                         /* try offset */
1351                                         val = GUINT32_TO_LE (ex_info->start);
1352                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353                                         /* need fault, too, probably */
1354                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1356                                         else
1357                                                 val = GUINT32_TO_LE (ex_info->len);
1358                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359                                         /* handler offset */
1360                                         val = GUINT32_TO_LE (ex_block->start);
1361                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362                                         /* handler len */
1363                                         val = GUINT32_TO_LE (ex_block->len);
1364                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365                                         finally_start = ex_block->start + ex_block->len;
1366                                         if (ex_block->extype) {
1367                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368                                                 return_val_if_nok (error, 0);
1369
1370                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1371                                         } else {
1372                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373                                                         val = ex_block->filter_offset;
1374                                                 else
1375                                                         val = 0;
1376                                         }
1377                                         val = GUINT32_TO_LE (val);
1378                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379                                         /*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", 
1380                                                         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);*/
1381                                 }
1382                         } else {
1383                                 g_error ("No clauses for ex info block %d", i);
1384                         }
1385                 }
1386         }
1387         return assembly->text_rva + idx;
1388 }
1389
1390 static guint32
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1392 {
1393         MONO_REQ_GC_NEUTRAL_MODE;
1394
1395         int i;
1396         MonoDynamicTable *table;
1397         guint32 *values;
1398         
1399         table = &assembly->tables [table_idx];
1400
1401         g_assert (col < table->columns);
1402
1403         values = table->values + table->columns;
1404         for (i = 1; i <= table->rows; ++i) {
1405                 if (values [col] == token)
1406                         return i;
1407                 values += table->columns;
1408         }
1409         return 0;
1410 }
1411
1412 /*
1413  * LOCKING: Acquires the loader lock. 
1414  */
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1417 {
1418         MONO_REQ_GC_NEUTRAL_MODE;
1419
1420         MonoCustomAttrInfo* res;
1421
1422         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1423
1424         if (!res)
1425                 return NULL;
1426
1427         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1428         res->cached = 0;
1429         return res;
1430 }
1431
1432 static gboolean
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1434 {
1435         MONO_REQ_GC_UNSAFE_MODE;
1436
1437         /* FIXME: Need to do more checks */
1438         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1440
1441                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1442                         return FALSE;
1443         }
1444
1445         return TRUE;
1446 }
1447
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1450 {
1451         MONO_REQ_GC_UNSAFE_MODE;
1452
1453         int i, index, count, not_visible;
1454         MonoCustomAttrInfo *ainfo;
1455         MonoReflectionCustomAttr *cattr;
1456
1457         if (!cattrs)
1458                 return NULL;
1459         /* FIXME: check in assembly the Run flag is set */
1460
1461         count = mono_array_length (cattrs);
1462
1463         /* Skip nonpublic attributes since MS.NET seems to do the same */
1464         /* FIXME: This needs to be done more globally */
1465         not_visible = 0;
1466         for (i = 0; i < count; ++i) {
1467                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468                 if (!custom_attr_visible (image, cattr))
1469                         not_visible ++;
1470         }
1471         count -= not_visible;
1472
1473         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1474
1475         ainfo->image = image;
1476         ainfo->num_attrs = count;
1477         ainfo->cached = alloc_img != NULL;
1478         index = 0;
1479         for (i = 0; i < count; ++i) {
1480                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481                 if (custom_attr_visible (image, cattr)) {
1482                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484                         ainfo->attrs [index].ctor = cattr->ctor->method;
1485                         ainfo->attrs [index].data = saved;
1486                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1487                         index ++;
1488                 }
1489         }
1490
1491         return ainfo;
1492 }
1493
1494 #ifndef DISABLE_REFLECTION_EMIT
1495 /*
1496  * LOCKING: Acquires the loader lock. 
1497  */
1498 static void
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1500 {
1501         MONO_REQ_GC_UNSAFE_MODE;
1502
1503         MonoCustomAttrInfo *ainfo, *tmp;
1504
1505         if (!cattrs || !mono_array_length (cattrs))
1506                 return;
1507
1508         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1509
1510         mono_loader_lock ();
1511         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1512         if (tmp)
1513                 mono_custom_attrs_free (tmp);
1514         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515         mono_loader_unlock ();
1516
1517 }
1518 #endif
1519
1520 void
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1522 {
1523         MONO_REQ_GC_NEUTRAL_MODE;
1524
1525         if (ainfo && !ainfo->cached)
1526                 g_free (ainfo);
1527 }
1528
1529 /*
1530  * idx is the table index of the object
1531  * type is one of MONO_CUSTOM_ATTR_*
1532  */
1533 static gboolean
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1535 {
1536         MONO_REQ_GC_UNSAFE_MODE;
1537
1538         MonoDynamicTable *table;
1539         MonoReflectionCustomAttr *cattr;
1540         guint32 *values;
1541         guint32 count, i, token;
1542         char blob_size [6];
1543         char *p = blob_size;
1544         
1545         mono_error_init (error);
1546
1547         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1548         if (!cattrs)
1549                 return TRUE;
1550         count = mono_array_length (cattrs);
1551         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552         table->rows += count;
1553         alloc_table (table, table->rows);
1554         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555         idx <<= MONO_CUSTOM_ATTR_BITS;
1556         idx |= type;
1557         for (i = 0; i < count; ++i) {
1558                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561                 if (!mono_error_ok (error)) goto fail;
1562                 type = mono_metadata_token_index (token);
1563                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564                 switch (mono_metadata_token_table (token)) {
1565                 case MONO_TABLE_METHOD:
1566                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1567                         /*
1568                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569                          * method, not the one returned by mono_image_create_token ().
1570                          */
1571                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1572                         break;
1573                 case MONO_TABLE_MEMBERREF:
1574                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1575                         break;
1576                 default:
1577                         g_warning ("got wrong token in custom attr");
1578                         continue;
1579                 }
1580                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1581                 p = blob_size;
1582                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585                 values += MONO_CUSTOM_ATTR_SIZE;
1586                 ++table->next_idx;
1587         }
1588
1589         return TRUE;
1590
1591 fail:
1592         return FALSE;
1593 }
1594
1595 static void
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1597 {
1598         MONO_REQ_GC_UNSAFE_MODE;
1599
1600         MonoDynamicTable *table;
1601         guint32 *values;
1602         guint32 count, i, idx;
1603         MonoReflectionPermissionSet *perm;
1604
1605         if (!permissions)
1606                 return;
1607
1608         count = mono_array_length (permissions);
1609         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610         table->rows += count;
1611         alloc_table (table, table->rows);
1612
1613         for (i = 0; i < mono_array_length (permissions); ++i) {
1614                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1615
1616                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1617
1618                 idx = mono_metadata_token_index (parent_token);
1619                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620                 switch (mono_metadata_token_table (parent_token)) {
1621                 case MONO_TABLE_TYPEDEF:
1622                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1623                         break;
1624                 case MONO_TABLE_METHOD:
1625                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1626                         break;
1627                 case MONO_TABLE_ASSEMBLY:
1628                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1629                         break;
1630                 default:
1631                         g_assert_not_reached ();
1632                 }
1633
1634                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635                 values [MONO_DECL_SECURITY_PARENT] = idx;
1636                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1637
1638                 ++table->next_idx;
1639         }
1640 }
1641
1642 /*
1643  * Fill in the MethodDef and ParamDef tables for a method.
1644  * This is used for both normal methods and constructors.
1645  */
1646 static gboolean
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1648 {
1649         MONO_REQ_GC_UNSAFE_MODE;
1650
1651         MonoDynamicTable *table;
1652         guint32 *values;
1653         guint i, count;
1654
1655         mono_error_init (error);
1656
1657         /* room in this table is already allocated */
1658         table = &assembly->tables [MONO_TABLE_METHOD];
1659         *mb->table_idx = table->next_idx ++;
1660         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663         values [MONO_METHOD_FLAGS] = mb->attrs;
1664         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666         return_val_if_nok (error, FALSE);
1667         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669
1670         table = &assembly->tables [MONO_TABLE_PARAM];
1671         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1672
1673         mono_image_add_decl_security (assembly, 
1674                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1675
1676         if (mb->pinfo) {
1677                 MonoDynamicTable *mtable;
1678                 guint32 *mvalues;
1679                 
1680                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1682                 
1683                 count = 0;
1684                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685                         if (mono_array_get (mb->pinfo, gpointer, i))
1686                                 count++;
1687                 }
1688                 table->rows += count;
1689                 alloc_table (table, table->rows);
1690                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692                         MonoReflectionParamBuilder *pb;
1693                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1695                                 values [MONO_PARAM_SEQUENCE] = i;
1696                                 if (pb->name != NULL) {
1697                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1698                                 } else {
1699                                         values [MONO_PARAM_NAME] = 0;
1700                                 }
1701                                 values += MONO_PARAM_SIZE;
1702                                 if (pb->marshal_info) {
1703                                         mtable->rows++;
1704                                         alloc_table (mtable, mtable->rows);
1705                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708                                         return_val_if_nok (error, FALSE);
1709                                 }
1710                                 pb->table_idx = table->next_idx++;
1711                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712                                         guint32 field_type = 0;
1713                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1714                                         mtable->rows ++;
1715                                         alloc_table (mtable, mtable->rows);
1716                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1720                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1721                                 }
1722                         }
1723                 }
1724         }
1725
1726         return TRUE;
1727 }
1728
1729 #ifndef DISABLE_REFLECTION_EMIT
1730 static gboolean
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1732 {
1733         MONO_REQ_GC_UNSAFE_MODE;
1734
1735         mono_error_init (error);
1736         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1737
1738         rmb->ilgen = mb->ilgen;
1739         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740         return_val_if_nok (error, FALSE);
1741         rmb->parameters = mb->parameters;
1742         rmb->generic_params = mb->generic_params;
1743         rmb->generic_container = mb->generic_container;
1744         rmb->opt_types = NULL;
1745         rmb->pinfo = mb->pinfo;
1746         rmb->attrs = mb->attrs;
1747         rmb->iattrs = mb->iattrs;
1748         rmb->call_conv = mb->call_conv;
1749         rmb->code = mb->code;
1750         rmb->type = mb->type;
1751         rmb->name = mb->name;
1752         rmb->table_idx = &mb->table_idx;
1753         rmb->init_locals = mb->init_locals;
1754         rmb->skip_visibility = FALSE;
1755         rmb->return_modreq = mb->return_modreq;
1756         rmb->return_modopt = mb->return_modopt;
1757         rmb->param_modreq = mb->param_modreq;
1758         rmb->param_modopt = mb->param_modopt;
1759         rmb->permissions = mb->permissions;
1760         rmb->mhandle = mb->mhandle;
1761         rmb->nrefs = 0;
1762         rmb->refs = NULL;
1763
1764         if (mb->dll) {
1765                 rmb->charset = mb->charset;
1766                 rmb->extra_flags = mb->extra_flags;
1767                 rmb->native_cc = mb->native_cc;
1768                 rmb->dllentry = mb->dllentry;
1769                 rmb->dll = mb->dll;
1770         }
1771
1772         return TRUE;
1773 }
1774
1775 static gboolean
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1777 {
1778         MONO_REQ_GC_UNSAFE_MODE;
1779
1780         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1781
1782         mono_error_init (error);
1783
1784         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1785
1786         rmb->ilgen = mb->ilgen;
1787         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788         return_val_if_nok (error, FALSE);
1789         rmb->parameters = mb->parameters;
1790         rmb->generic_params = NULL;
1791         rmb->generic_container = NULL;
1792         rmb->opt_types = NULL;
1793         rmb->pinfo = mb->pinfo;
1794         rmb->attrs = mb->attrs;
1795         rmb->iattrs = mb->iattrs;
1796         rmb->call_conv = mb->call_conv;
1797         rmb->code = NULL;
1798         rmb->type = mb->type;
1799         rmb->name = mono_string_new (mono_domain_get (), name);
1800         rmb->table_idx = &mb->table_idx;
1801         rmb->init_locals = mb->init_locals;
1802         rmb->skip_visibility = FALSE;
1803         rmb->return_modreq = NULL;
1804         rmb->return_modopt = NULL;
1805         rmb->param_modreq = mb->param_modreq;
1806         rmb->param_modopt = mb->param_modopt;
1807         rmb->permissions = mb->permissions;
1808         rmb->mhandle = mb->mhandle;
1809         rmb->nrefs = 0;
1810         rmb->refs = NULL;
1811
1812         return TRUE;
1813 }
1814
1815 static void
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1817 {
1818         MONO_REQ_GC_UNSAFE_MODE;
1819
1820         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1821
1822         rmb->ilgen = mb->ilgen;
1823         rmb->rtype = mb->rtype;
1824         rmb->parameters = mb->parameters;
1825         rmb->generic_params = NULL;
1826         rmb->generic_container = NULL;
1827         rmb->opt_types = NULL;
1828         rmb->pinfo = NULL;
1829         rmb->attrs = mb->attrs;
1830         rmb->iattrs = 0;
1831         rmb->call_conv = mb->call_conv;
1832         rmb->code = NULL;
1833         rmb->type = (MonoObject *) mb->owner;
1834         rmb->name = mb->name;
1835         rmb->table_idx = NULL;
1836         rmb->init_locals = mb->init_locals;
1837         rmb->skip_visibility = mb->skip_visibility;
1838         rmb->return_modreq = NULL;
1839         rmb->return_modopt = NULL;
1840         rmb->param_modreq = NULL;
1841         rmb->param_modopt = NULL;
1842         rmb->permissions = NULL;
1843         rmb->mhandle = mb->mhandle;
1844         rmb->nrefs = 0;
1845         rmb->refs = NULL;
1846 }       
1847 #endif
1848
1849 static gboolean
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1851 {
1852         MONO_REQ_GC_UNSAFE_MODE;
1853
1854         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855         MonoDynamicTable *table;
1856         guint32 *values;
1857         guint32 tok;
1858         MonoReflectionMethod *m;
1859         int i;
1860
1861         mono_error_init (error);
1862
1863         if (!mb->override_methods)
1864                 return TRUE;
1865
1866         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1868
1869                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1870                 table->rows ++;
1871                 alloc_table (table, table->rows);
1872                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1875
1876                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877                 return_val_if_nok (error, FALSE);
1878
1879                 switch (mono_metadata_token_table (tok)) {
1880                 case MONO_TABLE_MEMBERREF:
1881                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1882                         break;
1883                 case MONO_TABLE_METHOD:
1884                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1885                         break;
1886                 default:
1887                         g_assert_not_reached ();
1888                 }
1889                 values [MONO_METHODIMPL_DECLARATION] = tok;
1890         }
1891
1892         return TRUE;
1893 }
1894
1895 #ifndef DISABLE_REFLECTION_EMIT
1896 static gboolean
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1898 {
1899         MONO_REQ_GC_UNSAFE_MODE;
1900
1901         MonoDynamicTable *table;
1902         guint32 *values;
1903         ReflectionMethodBuilder rmb;
1904         int i;
1905
1906         mono_error_init (error);
1907
1908         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909             !mono_image_basic_method (&rmb, assembly, error))
1910                 return FALSE;
1911
1912         mb->table_idx = *rmb.table_idx;
1913
1914         if (mb->dll) { /* It's a P/Invoke method */
1915                 guint32 moduleref;
1916                 /* map CharSet values to on-disk values */
1917                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918                 int extra_flags = mb->extra_flags;
1919                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1920                 table->rows ++;
1921                 alloc_table (table, table->rows);
1922                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1923                 
1924                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1926                 if (mb->dllentry)
1927                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1928                 else
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1933                         table->rows ++;
1934                         alloc_table (table, table->rows);
1935                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1937                 }
1938         }
1939
1940         if (mb->generic_params) {
1941                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942                 table->rows += mono_array_length (mb->generic_params);
1943                 alloc_table (table, table->rows);
1944                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1946
1947                         mono_image_get_generic_param_info (
1948                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1949                 }
1950         }
1951
1952         return TRUE;
1953 }
1954
1955 static gboolean
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1957 {
1958         MONO_REQ_GC_UNSAFE_MODE;
1959
1960         ReflectionMethodBuilder rmb;
1961
1962         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1963                 return FALSE;
1964
1965         if (!mono_image_basic_method (&rmb, assembly, error))
1966                 return FALSE;
1967
1968         mb->table_idx = *rmb.table_idx;
1969
1970         return TRUE;
1971 }
1972 #endif
1973
1974 static char*
1975 type_get_fully_qualified_name (MonoType *type)
1976 {
1977         MONO_REQ_GC_NEUTRAL_MODE;
1978
1979         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1980 }
1981
1982 static char*
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1984 {
1985         MONO_REQ_GC_UNSAFE_MODE;
1986
1987         MonoClass *klass;
1988         MonoAssembly *ta;
1989
1990         klass = mono_class_from_mono_type (type);
1991         if (!klass) 
1992                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993         ta = klass->image->assembly;
1994         if (assembly_is_dynamic (ta) || (ta == ass)) {
1995                 if (klass->generic_class || klass->generic_container)
1996                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1998                 else
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2000         }
2001
2002         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2003 }
2004
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2007 static guint32
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2009 {
2010         MONO_REQ_GC_NEUTRAL_MODE;
2011
2012         SigBuffer buf;
2013         guint32 idx, i, token;
2014
2015         if (!assembly->save)
2016                 return 0;
2017
2018         sigbuffer_init (&buf, 32);
2019         
2020         sigbuffer_add_value (&buf, 0x06);
2021         /* encode custom attributes before the type */
2022         if (type->num_mods) {
2023                 for (i = 0; i < type->num_mods; ++i) {
2024                         if (field_image) {
2025                                 MonoError error;
2026                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2028
2029                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2030                         } else {
2031                                 token = type->modifiers [i].token;
2032                         }
2033
2034                         if (type->modifiers [i].required)
2035                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2036                         else
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2038
2039                         sigbuffer_add_value (&buf, token);
2040                 }
2041         }
2042         encode_type (assembly, type, &buf);
2043         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044         sigbuffer_free (&buf);
2045         return idx;
2046 }
2047 #endif
2048
2049 static guint32
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2051 {
2052         MONO_REQ_GC_UNSAFE_MODE;
2053
2054         mono_error_init (error);
2055
2056         SigBuffer buf;
2057         guint32 idx;
2058         guint32 typespec = 0;
2059         MonoType *type;
2060         MonoClass *klass;
2061
2062         init_type_builder_generics (fb->type);
2063
2064         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065         return_val_if_nok (error, 0);
2066         klass = mono_class_from_mono_type (type);
2067
2068         sigbuffer_init (&buf, 32);
2069         
2070         sigbuffer_add_value (&buf, 0x06);
2071         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2072         if (!is_ok (error))
2073                 goto fail;
2074         /* encode custom attributes before the type */
2075
2076         if (klass->generic_container)
2077                 typespec = create_typespec (assembly, type);
2078
2079         if (typespec) {
2080                 MonoGenericClass *gclass;
2081                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082                 encode_generic_class (assembly, gclass, &buf);
2083         } else {
2084                 encode_type (assembly, type, &buf);
2085         }
2086         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087         sigbuffer_free (&buf);
2088         return idx;
2089 fail:
2090         sigbuffer_free (&buf);
2091         return 0;
2092 }
2093
2094 static guint32
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2096 {
2097         MONO_REQ_GC_UNSAFE_MODE;
2098
2099         char blob_size [64];
2100         char *b = blob_size;
2101         char *box_val;
2102         char* buf;
2103         guint32 idx = 0, len = 0, dummy = 0;
2104
2105         buf = (char *)g_malloc (64);
2106         if (!val) {
2107                 *ret_type = MONO_TYPE_CLASS;
2108                 len = 4;
2109                 box_val = (char*)&dummy;
2110         } else {
2111                 box_val = ((char*)val) + sizeof (MonoObject);
2112                 *ret_type = val->vtable->klass->byval_arg.type;
2113         }
2114 handle_enum:
2115         switch (*ret_type) {
2116         case MONO_TYPE_BOOLEAN:
2117         case MONO_TYPE_U1:
2118         case MONO_TYPE_I1:
2119                 len = 1;
2120                 break;
2121         case MONO_TYPE_CHAR:
2122         case MONO_TYPE_U2:
2123         case MONO_TYPE_I2:
2124                 len = 2;
2125                 break;
2126         case MONO_TYPE_U4:
2127         case MONO_TYPE_I4:
2128         case MONO_TYPE_R4:
2129                 len = 4;
2130                 break;
2131         case MONO_TYPE_U8:
2132         case MONO_TYPE_I8:
2133                 len = 8;
2134                 break;
2135         case MONO_TYPE_R8:
2136                 len = 8;
2137                 break;
2138         case MONO_TYPE_VALUETYPE: {
2139                 MonoClass *klass = val->vtable->klass;
2140                 
2141                 if (klass->enumtype) {
2142                         *ret_type = mono_class_enum_basetype (klass)->type;
2143                         goto handle_enum;
2144                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2145                         len = 8;
2146                 } else 
2147                         g_error ("we can't encode valuetypes, we should have never reached this line");
2148                 break;
2149         }
2150         case MONO_TYPE_CLASS:
2151                 break;
2152         case MONO_TYPE_STRING: {
2153                 MonoString *str = (MonoString*)val;
2154                 /* there is no signature */
2155                 len = str->length * 2;
2156                 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2158                 {
2159                         char *swapped = g_malloc (2 * mono_string_length (str));
2160                         const char *p = (const char*)mono_string_chars (str);
2161
2162                         swap_with_size (swapped, p, 2, mono_string_length (str));
2163                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2164                         g_free (swapped);
2165                 }
2166 #else
2167                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2168 #endif
2169
2170                 g_free (buf);
2171                 return idx;
2172         }
2173         case MONO_TYPE_GENERICINST:
2174                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2175                 goto handle_enum;
2176         default:
2177                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2178         }
2179
2180         /* there is no signature */
2181         mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184         swap_with_size (blob_size, box_val, len, 1);
2185         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2186 #else
2187         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2188 #endif
2189
2190         g_free (buf);
2191         return idx;
2192 }
2193
2194 static guint32
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2196 {
2197         MONO_REQ_GC_UNSAFE_MODE;
2198
2199         mono_error_init (error);
2200
2201         char *str;
2202         SigBuffer buf;
2203         guint32 idx, len;
2204
2205         sigbuffer_init (&buf, 32);
2206
2207         sigbuffer_add_value (&buf, minfo->type);
2208
2209         switch (minfo->type) {
2210         case MONO_NATIVE_BYVALTSTR:
2211         case MONO_NATIVE_BYVALARRAY:
2212                 sigbuffer_add_value (&buf, minfo->count);
2213                 break;
2214         case MONO_NATIVE_LPARRAY:
2215                 if (minfo->eltype || minfo->has_size) {
2216                         sigbuffer_add_value (&buf, minfo->eltype);
2217                         if (minfo->has_size) {
2218                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2220
2221                                 /* LAMESPEC: ElemMult is undocumented */
2222                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2223                         }
2224                 }
2225                 break;
2226         case MONO_NATIVE_SAFEARRAY:
2227                 if (minfo->eltype)
2228                         sigbuffer_add_value (&buf, minfo->eltype);
2229                 break;
2230         case MONO_NATIVE_CUSTOM:
2231                 if (minfo->guid) {
2232                         str = mono_string_to_utf8 (minfo->guid);
2233                         len = strlen (str);
2234                         sigbuffer_add_value (&buf, len);
2235                         sigbuffer_add_mem (&buf, str, len);
2236                         g_free (str);
2237                 } else {
2238                         sigbuffer_add_value (&buf, 0);
2239                 }
2240                 /* native type name */
2241                 sigbuffer_add_value (&buf, 0);
2242                 /* custom marshaler type name */
2243                 if (minfo->marshaltype || minfo->marshaltyperef) {
2244                         if (minfo->marshaltyperef) {
2245                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246                                 if (!is_ok (error)) {
2247                                         sigbuffer_free (&buf);
2248                                         return 0;
2249                                 }
2250                                 str = type_get_fully_qualified_name (marshaltype);
2251                         } else
2252                                 str = mono_string_to_utf8 (minfo->marshaltype);
2253                         len = strlen (str);
2254                         sigbuffer_add_value (&buf, len);
2255                         sigbuffer_add_mem (&buf, str, len);
2256                         g_free (str);
2257                 } else {
2258                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 if (minfo->mcookie) {
2262                         str = mono_string_to_utf8 (minfo->mcookie);
2263                         len = strlen (str);
2264                         sigbuffer_add_value (&buf, len);
2265                         sigbuffer_add_mem (&buf, str, len);
2266                         g_free (str);
2267                 } else {
2268                         sigbuffer_add_value (&buf, 0);
2269                 }
2270                 break;
2271         default:
2272                 break;
2273         }
2274         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275         sigbuffer_free (&buf);
2276         return idx;
2277 }
2278
2279 static void
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2281 {
2282         MONO_REQ_GC_UNSAFE_MODE;
2283
2284         mono_error_init (error);
2285
2286         MonoDynamicTable *table;
2287         guint32 *values;
2288
2289         /* maybe this fixup should be done in the C# code */
2290         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292         table = &assembly->tables [MONO_TABLE_FIELD];
2293         fb->table_idx = table->next_idx ++;
2294         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297         values [MONO_FIELD_FLAGS] = fb->attrs;
2298         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299         return_if_nok (error);
2300
2301
2302         if (fb->offset != -1) {
2303                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2304                 table->rows ++;
2305                 alloc_table (table, table->rows);
2306                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2309         }
2310         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2313                 table->rows ++;
2314                 alloc_table (table, table->rows);
2315                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318                 values [MONO_CONSTANT_TYPE] = field_type;
2319                 values [MONO_CONSTANT_PADDING] = 0;
2320         }
2321         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2322                 guint32 rva_idx;
2323                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2324                 table->rows ++;
2325                 alloc_table (table, table->rows);
2326                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2328                 /*
2329                  * We store it in the code section because it's simpler for now.
2330                  */
2331                 if (fb->rva_data) {
2332                         if (mono_array_length (fb->rva_data) >= 10)
2333                                 stream_data_align (&assembly->code);
2334                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2335                 } else
2336                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2338         }
2339         if (fb->marshal_info) {
2340                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2341                 table->rows ++;
2342                 alloc_table (table, table->rows);
2343                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346                 return_if_nok (error);
2347         }
2348 }
2349
2350 static guint32
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2352 {
2353         MONO_REQ_GC_UNSAFE_MODE;
2354
2355         mono_error_init (error);
2356
2357         SigBuffer buf;
2358         guint32 nparams = 0;
2359         MonoReflectionMethodBuilder *mb = fb->get_method;
2360         MonoReflectionMethodBuilder *smb = fb->set_method;
2361         guint32 idx, i;
2362
2363         if (mb && mb->parameters)
2364                 nparams = mono_array_length (mb->parameters);
2365         if (!mb && smb && smb->parameters)
2366                 nparams = mono_array_length (smb->parameters) - 1;
2367         sigbuffer_init (&buf, 32);
2368         if (fb->call_conv & 0x20)
2369                 sigbuffer_add_byte (&buf, 0x28);
2370         else
2371                 sigbuffer_add_byte (&buf, 0x08);
2372         sigbuffer_add_value (&buf, nparams);
2373         if (mb) {
2374                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2375                 if (!is_ok (error))
2376                         goto fail;
2377                 for (i = 0; i < nparams; ++i) {
2378                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379                         encode_reflection_type (assembly, pt, &buf, error);
2380                         if (!is_ok (error))
2381                                 goto fail;
2382                 }
2383         } else if (smb && smb->parameters) {
2384                 /* the property type is the last param */
2385                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2386                 if (!is_ok (error))
2387                         goto fail;
2388
2389                 for (i = 0; i < nparams; ++i) {
2390                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391                         encode_reflection_type (assembly, pt, &buf, error);
2392                         if (!is_ok (error))
2393                                 goto fail;
2394                 }
2395         } else {
2396                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2397                 if (!is_ok (error))
2398                         goto fail;
2399         }
2400
2401         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402         sigbuffer_free (&buf);
2403         return idx;
2404 fail:
2405         sigbuffer_free (&buf);
2406         return 0;
2407 }
2408
2409 static void
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         mono_error_init (error);
2415
2416         MonoDynamicTable *table;
2417         guint32 *values;
2418         guint num_methods = 0;
2419         guint32 semaidx;
2420
2421         /* 
2422          * we need to set things in the following tables:
2423          * PROPERTYMAP (info already filled in _get_type_info ())
2424          * PROPERTY    (rows already preallocated in _get_type_info ())
2425          * METHOD      (method info already done with the generic method code)
2426          * METHODSEMANTICS
2427          * CONSTANT
2428          */
2429         table = &assembly->tables [MONO_TABLE_PROPERTY];
2430         pb->table_idx = table->next_idx ++;
2431         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435         return_if_nok (error);
2436
2437
2438         /* FIXME: we still don't handle 'other' methods */
2439         if (pb->get_method) num_methods ++;
2440         if (pb->set_method) num_methods ++;
2441
2442         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443         table->rows += num_methods;
2444         alloc_table (table, table->rows);
2445
2446         if (pb->get_method) {
2447                 semaidx = table->next_idx ++;
2448                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2452         }
2453         if (pb->set_method) {
2454                 semaidx = table->next_idx ++;
2455                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2459         }
2460         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2463                 table->rows ++;
2464                 alloc_table (table, table->rows);
2465                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468                 values [MONO_CONSTANT_TYPE] = field_type;
2469                 values [MONO_CONSTANT_PADDING] = 0;
2470         }
2471 }
2472
2473 static void
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2475 {
2476         MONO_REQ_GC_UNSAFE_MODE;
2477
2478         MonoDynamicTable *table;
2479         guint32 *values;
2480         guint num_methods = 0;
2481         guint32 semaidx;
2482
2483         /* 
2484          * we need to set things in the following tables:
2485          * EVENTMAP (info already filled in _get_type_info ())
2486          * EVENT    (rows already preallocated in _get_type_info ())
2487          * METHOD      (method info already done with the generic method code)
2488          * METHODSEMANTICS
2489          */
2490         table = &assembly->tables [MONO_TABLE_EVENT];
2491         eb->table_idx = table->next_idx ++;
2492         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494         values [MONO_EVENT_FLAGS] = eb->attrs;
2495         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496         return_if_nok (error);
2497         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2498
2499         /*
2500          * FIXME: we still don't handle 'other' methods 
2501          */
2502         if (eb->add_method) num_methods ++;
2503         if (eb->remove_method) num_methods ++;
2504         if (eb->raise_method) num_methods ++;
2505
2506         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507         table->rows += num_methods;
2508         alloc_table (table, table->rows);
2509
2510         if (eb->add_method) {
2511                 semaidx = table->next_idx ++;
2512                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2516         }
2517         if (eb->remove_method) {
2518                 semaidx = table->next_idx ++;
2519                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2523         }
2524         if (eb->raise_method) {
2525                 semaidx = table->next_idx ++;
2526                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2530         }
2531 }
2532
2533 static void
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2535 {
2536         MONO_REQ_GC_UNSAFE_MODE;
2537
2538         mono_error_init (error);
2539
2540         MonoDynamicTable *table;
2541         guint32 num_constraints, i;
2542         guint32 *values;
2543         guint32 table_idx;
2544
2545         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546         num_constraints = gparam->iface_constraints ?
2547                 mono_array_length (gparam->iface_constraints) : 0;
2548         table->rows += num_constraints;
2549         if (gparam->base_type)
2550                 table->rows++;
2551         alloc_table (table, table->rows);
2552
2553         if (gparam->base_type) {
2554                 table_idx = table->next_idx ++;
2555                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2556
2557                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2558                 return_if_nok (error);
2559                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2561         }
2562
2563         for (i = 0; i < num_constraints; i++) {
2564                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565                         gparam->iface_constraints, gpointer, i);
2566
2567                 table_idx = table->next_idx ++;
2568                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2569
2570                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2571                 return_if_nok (error);
2572
2573                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2575         }
2576 }
2577
2578 static void
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2580 {
2581         MONO_REQ_GC_UNSAFE_MODE;
2582
2583         GenericParamTableEntry *entry;
2584
2585         /*
2586          * The GenericParam table must be sorted according to the `owner' field.
2587          * We need to do this sorting prior to writing the GenericParamConstraint
2588          * table, since we have to use the final GenericParam table indices there
2589          * and they must also be sorted.
2590          */
2591
2592         entry = g_new0 (GenericParamTableEntry, 1);
2593         entry->owner = owner;
2594         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596         entry->gparam = gparam;
2597         
2598         g_ptr_array_add (assembly->gen_params, entry);
2599 }
2600
2601 static gboolean
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2603 {
2604         MONO_REQ_GC_UNSAFE_MODE;
2605
2606         MonoDynamicTable *table;
2607         MonoGenericParam *param;
2608         guint32 *values;
2609         guint32 table_idx;
2610
2611         mono_error_init (error);
2612
2613         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614         table_idx = table->next_idx ++;
2615         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2616
2617         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618         return_val_if_nok (error, FALSE);
2619
2620         param = gparam_type->data.generic_param;
2621
2622         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2626
2627         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2628                 return FALSE;
2629
2630         encode_constraints (entry->gparam, table_idx, assembly, error);
2631         return_val_if_nok (error, FALSE);
2632
2633         return TRUE;
2634 }
2635
2636 static guint32
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2638 {
2639         MONO_REQ_GC_UNSAFE_MODE;
2640
2641         MonoDynamicTable *table;
2642         guint32 token;
2643         guint32 *values;
2644         guint32 cols [MONO_ASSEMBLY_SIZE];
2645         const char *pubkey;
2646         guint32 publen;
2647
2648         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2649                 return token;
2650
2651         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653                 token = table->next_idx ++;
2654                 table->rows ++;
2655                 alloc_table (table, table->rows);
2656                 values = table->values + token * MONO_MODULEREF_SIZE;
2657                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2658
2659                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2662
2663                 return token;
2664         }
2665         
2666         if (assembly_is_dynamic (image->assembly))
2667                 /* FIXME: */
2668                 memset (cols, 0, sizeof (cols));
2669         else {
2670                 /* image->assembly->image is the manifest module */
2671                 image = image->assembly->image;
2672                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2673         }
2674
2675         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676         token = table->next_idx ++;
2677         table->rows ++;
2678         alloc_table (table, table->rows);
2679         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2688
2689         if (strcmp ("", image->assembly->aname.culture)) {
2690                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691                                 image->assembly->aname.culture);
2692         }
2693
2694         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695                 guchar pubtoken [9];
2696                 pubtoken [0] = 8;
2697                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699         } else {
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2701         }
2702         token <<= MONO_RESOLUTION_SCOPE_BITS;
2703         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2705         return token;
2706 }
2707
2708 static guint32
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2710 {
2711         MONO_REQ_GC_NEUTRAL_MODE;
2712
2713         MonoDynamicTable *table;
2714         guint32 *values;
2715         guint32 token;
2716         SigBuffer buf;
2717
2718         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2719                 return token;
2720
2721         sigbuffer_init (&buf, 32);
2722         switch (type->type) {
2723         case MONO_TYPE_FNPTR:
2724         case MONO_TYPE_PTR:
2725         case MONO_TYPE_SZARRAY:
2726         case MONO_TYPE_ARRAY:
2727         case MONO_TYPE_VAR:
2728         case MONO_TYPE_MVAR:
2729         case MONO_TYPE_GENERICINST:
2730                 encode_type (assembly, type, &buf);
2731                 break;
2732         case MONO_TYPE_CLASS:
2733         case MONO_TYPE_VALUETYPE: {
2734                 MonoClass *k = mono_class_from_mono_type (type);
2735                 if (!k || !k->generic_container) {
2736                         sigbuffer_free (&buf);
2737                         return 0;
2738                 }
2739                 encode_type (assembly, type, &buf);
2740                 break;
2741         }
2742         default:
2743                 sigbuffer_free (&buf);
2744                 return 0;
2745         }
2746
2747         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748         if (assembly->save) {
2749                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750                 alloc_table (table, table->rows + 1);
2751                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752                 values [MONO_TYPESPEC_SIGNATURE] = token;
2753         }
2754         sigbuffer_free (&buf);
2755
2756         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2758         table->next_idx ++;
2759         return token;
2760 }
2761
2762 static guint32
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2764 {
2765         MONO_REQ_GC_UNSAFE_MODE;
2766
2767         MonoDynamicTable *table;
2768         guint32 *values;
2769         guint32 token, scope, enclosing;
2770         MonoClass *klass;
2771
2772         /* if the type requires a typespec, we must try that first*/
2773         if (try_typespec && (token = create_typespec (assembly, type)))
2774                 return token;
2775         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2776         if (token)
2777                 return token;
2778         klass = mono_class_from_mono_type (type);
2779         if (!klass)
2780                 klass = mono_class_from_mono_type (type);
2781
2782         /*
2783          * If it's in the same module and not a generic type parameter:
2784          */
2785         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2786                         (type->type != MONO_TYPE_MVAR)) {
2787                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2790                 return token;
2791         }
2792
2793         if (klass->nested_in) {
2794                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795                 /* get the typeref idx of the enclosing type */
2796                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798         } else {
2799                 scope = resolution_scope_from_image (assembly, klass->image);
2800         }
2801         table = &assembly->tables [MONO_TABLE_TYPEREF];
2802         if (assembly->save) {
2803                 alloc_table (table, table->rows + 1);
2804                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805                 values [MONO_TYPEREF_SCOPE] = scope;
2806                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2808         }
2809         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811         table->next_idx ++;
2812         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2813         return token;
2814 }
2815
2816 /*
2817  * Despite the name, we handle also TypeSpec (with the above helper).
2818  */
2819 static guint32
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2821 {
2822         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2823 }
2824
2825 #ifndef DISABLE_REFLECTION_EMIT
2826 static guint32
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2828 {
2829         MONO_REQ_GC_NEUTRAL_MODE;
2830
2831         MonoDynamicTable *table;
2832         guint32 *values;
2833         guint32 token, pclass;
2834
2835         switch (parent & MONO_TYPEDEFORREF_MASK) {
2836         case MONO_TYPEDEFORREF_TYPEREF:
2837                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838                 break;
2839         case MONO_TYPEDEFORREF_TYPESPEC:
2840                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841                 break;
2842         case MONO_TYPEDEFORREF_TYPEDEF:
2843                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2844                 break;
2845         default:
2846                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2847                 return 0;
2848         }
2849         /* extract the index */
2850         parent >>= MONO_TYPEDEFORREF_BITS;
2851
2852         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2853
2854         if (assembly->save) {
2855                 alloc_table (table, table->rows + 1);
2856                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2860         }
2861
2862         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2863         table->next_idx ++;
2864
2865         return token;
2866 }
2867
2868 /*
2869  * Insert a memberef row into the metadata: the token that point to the memberref
2870  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871  * mono_image_get_fieldref_token()).
2872  * The sig param is an index to an already built signature.
2873  */
2874 static guint32
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2876 {
2877         MONO_REQ_GC_NEUTRAL_MODE;
2878
2879         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880         return mono_image_add_memberef_row (assembly, parent, name, sig);
2881 }
2882
2883
2884 static guint32
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2886 {
2887         MONO_REQ_GC_NEUTRAL_MODE;
2888
2889         guint32 token;
2890         MonoMethodSignature *sig;
2891         
2892         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2893
2894         if (create_typespec) {
2895                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2896                 if (token)
2897                         return token;
2898         } 
2899
2900         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901         if (token && !create_typespec)
2902                 return token;
2903
2904         g_assert (!method->is_inflated);
2905         if (!token) {
2906                 /*
2907                  * A methodref signature can't contain an unmanaged calling convention.
2908                  */
2909                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911                         sig->call_convention = MONO_CALL_DEFAULT;
2912                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913                         method->name,  method_encode_signature (assembly, sig));
2914                 g_free (sig);
2915                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2916         }
2917
2918         if (create_typespec) {
2919                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922
2923                 if (assembly->save) {
2924                         guint32 *values;
2925
2926                         alloc_table (table, table->rows + 1);
2927                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928                         values [MONO_METHODSPEC_METHOD] = token;
2929                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2930                 }
2931
2932                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933                 table->next_idx ++;
2934                 /*methodspec and memberef tokens are diferent, */
2935                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2936                 return token;
2937         }
2938         return token;
2939 }
2940
2941 static guint32
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2943 {
2944         guint32 token, parent, sig;
2945         ReflectionMethodBuilder rmb;
2946         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2947         
2948         mono_error_init (error);
2949         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2950         if (token)
2951                 return token;
2952
2953         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2954                 return 0;
2955
2956         /*
2957          * A methodref signature can't contain an unmanaged calling convention.
2958          * Since some flags are encoded as part of call_conv, we need to check against it.
2959         */
2960         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2962
2963         sig = method_builder_encode_signature (assembly, &rmb, error);
2964         return_val_if_nok (error, 0);
2965
2966         if (tb->generic_params) {
2967                 parent = create_generic_typespec (assembly, tb, error);
2968                 return_val_if_nok (error, 0);
2969         } else {
2970                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971                 return_val_if_nok (error, 0);
2972
2973                 parent = mono_image_typedef_or_ref (assembly, t);
2974         }
2975
2976         char *name = mono_string_to_utf8 (method->name);
2977
2978         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979         g_free (name);
2980
2981         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2982
2983         return token;
2984 }
2985
2986 static guint32
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988                                      const gchar *name, guint32 sig)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 token;
2992         guint32 *values;
2993         
2994         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2995
2996         if (assembly->save) {
2997                 alloc_table (table, table->rows + 1);
2998                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999                 values [MONO_MEMBERREF_CLASS] = original;
3000                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3012 {
3013         SigBuffer buf;
3014         int i;
3015         guint32 nparams = mono_array_length (mb->generic_params);
3016         guint32 idx;
3017
3018         if (!assembly->save)
3019                 return 0;
3020
3021         sigbuffer_init (&buf, 32);
3022
3023         sigbuffer_add_value (&buf, 0xa);
3024         sigbuffer_add_value (&buf, nparams);
3025
3026         for (i = 0; i < nparams; i++) {
3027                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028                 sigbuffer_add_value (&buf, i);
3029         }
3030
3031         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032         sigbuffer_free (&buf);
3033         return idx;
3034 }
3035
3036 static guint32
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3038 {
3039         MonoDynamicTable *table;
3040         guint32 *values;
3041         guint32 token, mtoken = 0;
3042
3043         mono_error_init (error);
3044         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3045         if (token)
3046                 return token;
3047
3048         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3049
3050         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051         if (!mono_error_ok (error))
3052                 return 0;
3053
3054         switch (mono_metadata_token_table (mtoken)) {
3055         case MONO_TABLE_MEMBERREF:
3056                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057                 break;
3058         case MONO_TABLE_METHOD:
3059                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060                 break;
3061         default:
3062                 g_assert_not_reached ();
3063         }
3064
3065         if (assembly->save) {
3066                 alloc_table (table, table->rows + 1);
3067                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068                 values [MONO_METHODSPEC_METHOD] = mtoken;
3069                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3070         }
3071
3072         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073         table->next_idx ++;
3074
3075         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3076         return token;
3077 }
3078
3079 static guint32
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3081 {
3082         guint32 token;
3083
3084         mono_error_init (error);
3085
3086         if (mb->generic_params && create_methodspec) 
3087                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3088
3089         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3090         if (token)
3091                 return token;
3092
3093         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094         if (!mono_error_ok (error))
3095                 return 0;
3096         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3097         return token;
3098 }
3099
3100 static guint32
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3102 {
3103         guint32 token, parent, sig;
3104         ReflectionMethodBuilder rmb;
3105         char *name;
3106         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3107         
3108         mono_error_init (error);
3109         
3110         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3111         if (token)
3112                 return token;
3113
3114         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115                 return 0;
3116
3117         if (tb->generic_params) {
3118                 parent = create_generic_typespec (assembly, tb, error);
3119                 return_val_if_nok (error, 0);
3120         } else {
3121                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122                 return_val_if_nok (error, 0);
3123                 parent = mono_image_typedef_or_ref (assembly, type);
3124         }
3125         
3126         name = mono_string_to_utf8 (rmb.name);
3127         sig = method_builder_encode_signature (assembly, &rmb, error);
3128         return_val_if_nok (error, 0);
3129
3130         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3131
3132         g_free (name);
3133         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3134         return token;
3135 }
3136 #endif
3137
3138 static gboolean
3139 is_field_on_inst (MonoClassField *field)
3140 {
3141         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3142 }
3143
3144 /*
3145  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3146  */
3147 static MonoType*
3148 get_field_on_inst_generic_type (MonoClassField *field)
3149 {
3150         MonoClass *klass, *gtd;
3151         MonoDynamicGenericClass *dgclass;
3152         int field_index;
3153
3154         g_assert (is_field_on_inst (field));
3155
3156         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3157
3158         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159                 field_index = field - dgclass->fields;
3160                 return dgclass->field_generic_types [field_index];              
3161         }
3162
3163         klass = field->parent;
3164         gtd = klass->generic_class->container_class;
3165
3166         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167                 field_index = field - klass->fields;
3168                 return gtd->fields [field_index].type;
3169         }
3170
3171         g_assert_not_reached ();
3172         return 0;
3173 }
3174
3175 #ifndef DISABLE_REFLECTION_EMIT
3176 static guint32
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3178 {
3179         MonoType *type;
3180         guint32 token;
3181
3182         g_assert (field);
3183         g_assert (field->parent);
3184
3185         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186         if (token)
3187                 return token;
3188
3189         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190                 int index = field - field->parent->fields;
3191                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3192         } else {
3193                 if (is_field_on_inst (field))
3194                         type = get_field_on_inst_generic_type (field);
3195                 else
3196                         type = mono_field_get_type (field);
3197         }
3198         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199                                                                                         mono_field_get_name (field),
3200                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3201         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3202         return token;
3203 }
3204
3205 static guint32
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3207 {
3208         guint32 token;
3209         MonoClass *klass;
3210         MonoGenericClass *gclass;
3211         MonoType *type;
3212         char *name;
3213
3214         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215         if (token)
3216                 return token;
3217         if (is_sre_field_builder (mono_object_class (f->fb))) {
3218                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220                 return_val_if_nok (error, 0);
3221                 klass = mono_class_from_mono_type (type);
3222                 gclass = type->data.generic_class;
3223                 g_assert (gclass->is_dynamic);
3224
3225                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226                 return_val_if_nok (error, 0);
3227                 name = mono_string_to_utf8 (fb->name);
3228                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3229                 g_free (name);          
3230         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3231                 guint32 sig;
3232                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3233
3234                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235                 return_val_if_nok (error, 0);
3236                 klass = mono_class_from_mono_type (type);
3237
3238                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3240         } else {
3241                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243         }
3244
3245         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3246         return token;
3247 }
3248
3249 static guint32
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3251 {
3252         guint32 sig, token;
3253         MonoClass *klass;
3254         MonoGenericClass *gclass;
3255         MonoType *type;
3256
3257         mono_error_init (error);
3258
3259         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3260
3261         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3262         if (token)
3263                 return token;
3264
3265         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267                 ReflectionMethodBuilder rmb;
3268                 char *name;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 gclass = type->data.generic_class;
3275                 g_assert (gclass->is_dynamic);
3276
3277                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278                         return 0;
3279
3280                 sig = method_builder_encode_signature (assembly, &rmb, error);
3281                 return_val_if_nok (error, 0);
3282
3283                 name = mono_string_to_utf8 (rmb.name);
3284
3285                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3286                 g_free (name);
3287         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3289
3290                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291                 return_val_if_nok (error, 0);
3292                 klass = mono_class_from_mono_type (type);
3293
3294                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3296         } else {
3297                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3299         }
3300
3301
3302         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3303         return token;
3304 }
3305
3306 static MonoMethod*
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 {
3309         MonoClass *klass;
3310         MonoGenericContext tmp_context;
3311         MonoType **type_argv;
3312         MonoGenericInst *ginst;
3313         MonoMethod *method, *inflated;
3314         int count, i;
3315
3316         mono_error_init (error);
3317
3318         init_type_builder_generics ((MonoObject*)m->inst);
3319
3320         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321         return_val_if_nok (error, NULL);
3322
3323         klass = method->klass;
3324
3325         if (m->method_args == NULL)
3326                 return method;
3327
3328         if (method->is_inflated)
3329                 method = ((MonoMethodInflated *) method)->declaring;
3330
3331         count = mono_array_length (m->method_args);
3332
3333         type_argv = g_new0 (MonoType *, count);
3334         for (i = 0; i < count; i++) {
3335                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337                 return_val_if_nok (error, NULL);
3338         }
3339         ginst = mono_metadata_get_generic_inst (count, type_argv);
3340         g_free (type_argv);
3341
3342         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343         tmp_context.method_inst = ginst;
3344
3345         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346         mono_error_assert_ok (error);
3347         return inflated;
3348 }
3349
3350 static guint32
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3352 {
3353         guint32 sig, token = 0;
3354         MonoType *type;
3355         MonoClass *klass;
3356
3357         mono_error_init (error);
3358
3359         if (m->method_args) {
3360                 MonoMethod *inflated;
3361
3362                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363                 return_val_if_nok (error, 0);
3364
3365                 if (create_methodspec)
3366                         token = mono_image_get_methodspec_token (assembly, inflated);
3367                 else
3368                         token = mono_image_get_inflated_method_token (assembly, inflated);
3369                 return token;
3370         }
3371
3372         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3373         if (token)
3374                 return token;
3375
3376         if (is_sre_method_builder (mono_object_class (m->mb))) {
3377                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378                 MonoGenericClass *gclass;
3379                 ReflectionMethodBuilder rmb;
3380                 char *name;
3381
3382                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383                 return_val_if_nok (error, 0);
3384                 klass = mono_class_from_mono_type (type);
3385                 gclass = type->data.generic_class;
3386                 g_assert (gclass->is_dynamic);
3387
3388                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389                         return 0;
3390
3391                 sig = method_builder_encode_signature (assembly, &rmb, error);
3392                 return_val_if_nok (error, 0);
3393
3394                 name = mono_string_to_utf8 (rmb.name);
3395
3396                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3397                 g_free (name);          
3398         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3400
3401                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402                 return_val_if_nok (error, 0);
3403                 klass = mono_class_from_mono_type (type);
3404
3405                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3407         } else {
3408                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410         }
3411
3412         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3413         return token;
3414 }
3415
3416 static guint32
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3418 {
3419         SigBuffer buf;
3420         int i;
3421         guint32 nparams = context->method_inst->type_argc;
3422         guint32 idx;
3423
3424         if (!assembly->save)
3425                 return 0;
3426
3427         sigbuffer_init (&buf, 32);
3428         /*
3429          * FIXME: vararg, explicit_this, differenc call_conv values...
3430          */
3431         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432         sigbuffer_add_value (&buf, nparams);
3433
3434         for (i = 0; i < nparams; i++)
3435                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3436
3437         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438         sigbuffer_free (&buf);
3439         return idx;
3440 }
3441
3442 static guint32
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3444 {
3445         MonoDynamicTable *table;
3446         guint32 *values;
3447         guint32 token, mtoken = 0, sig;
3448         MonoMethodInflated *imethod;
3449         MonoMethod *declaring;
3450
3451         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3452
3453         g_assert (method->is_inflated);
3454         imethod = (MonoMethodInflated *) method;
3455         declaring = imethod->declaring;
3456
3457         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3459
3460         if (!mono_method_signature (declaring)->generic_param_count)
3461                 return mtoken;
3462
3463         switch (mono_metadata_token_table (mtoken)) {
3464         case MONO_TABLE_MEMBERREF:
3465                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3466                 break;
3467         case MONO_TABLE_METHOD:
3468                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469                 break;
3470         default:
3471                 g_assert_not_reached ();
3472         }
3473
3474         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3475
3476         if (assembly->save) {
3477                 alloc_table (table, table->rows + 1);
3478                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479                 values [MONO_METHODSPEC_METHOD] = mtoken;
3480                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481         }
3482
3483         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3484         table->next_idx ++;
3485
3486         return token;
3487 }
3488
3489 static guint32
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3491 {
3492         MonoMethodInflated *imethod;
3493         guint32 token;
3494         
3495         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3496         if (token)
3497                 return token;
3498
3499         g_assert (method->is_inflated);
3500         imethod = (MonoMethodInflated *) method;
3501
3502         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503                 token = method_encode_methodspec (assembly, method);
3504         } else {
3505                 guint32 sig = method_encode_signature (
3506                         assembly, mono_method_signature (imethod->declaring));
3507                 token = mono_image_get_memberref_token (
3508                         assembly, &method->klass->byval_arg, method->name, sig);
3509         }
3510
3511         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3512         return token;
3513 }
3514
3515 static guint32
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3517 {
3518         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519         guint32 sig, token;
3520
3521         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522         token = mono_image_get_memberref_token (
3523                 assembly, &m->klass->byval_arg, m->name, sig);
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3530 {
3531         MonoDynamicTable *table;
3532         MonoClass *klass;
3533         MonoType *type;
3534         guint32 *values;
3535         guint32 token;
3536         SigBuffer buf;
3537         int count, i;
3538
3539         /*
3540          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542          * Because of this, we must not insert it into the `typeref' hash table.
3543          */
3544         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545         return_val_if_nok (error, 0);
3546         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3547         if (token)
3548                 return token;
3549
3550         sigbuffer_init (&buf, 32);
3551
3552         g_assert (tb->generic_params);
3553         klass = mono_class_from_mono_type (type);
3554
3555         if (tb->generic_container)
3556                 mono_reflection_create_generic_class (tb);
3557
3558         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559         g_assert (klass->generic_container);
3560         sigbuffer_add_value (&buf, klass->byval_arg.type);
3561         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562
3563         count = mono_array_length (tb->generic_params);
3564         sigbuffer_add_value (&buf, count);
3565         for (i = 0; i < count; i++) {
3566                 MonoReflectionGenericParam *gparam;
3567
3568                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3570                 if (!is_ok (error))
3571                         goto fail;
3572
3573                 encode_type (assembly, gparam_type, &buf);
3574         }
3575
3576         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3577
3578         if (assembly->save) {
3579                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580                 alloc_table (table, table->rows + 1);
3581                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582                 values [MONO_TYPESPEC_SIGNATURE] = token;
3583         }
3584         sigbuffer_free (&buf);
3585
3586         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3588         table->next_idx ++;
3589         return token;
3590 fail:
3591         sigbuffer_free (&buf);
3592         return 0;
3593 }
3594
3595 /*
3596  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3597  */
3598 static MonoType*
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3600 {
3601         int i, count, len, pos;
3602         MonoType *t;
3603
3604         mono_error_init (error);
3605
3606         count = 0;
3607         if (modreq)
3608                 count += mono_array_length (modreq);
3609         if (modopt)
3610                 count += mono_array_length (modopt);
3611
3612         if (count == 0)
3613                 return mono_metadata_type_dup (NULL, type);
3614
3615         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3616         t = (MonoType *)g_malloc (len);
3617         memcpy (t, type, MONO_SIZEOF_TYPE);
3618
3619         t->num_mods = count;
3620         pos = 0;
3621         if (modreq) {
3622                 for (i = 0; i < mono_array_length (modreq); ++i) {
3623                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3624                         if (!is_ok (error))
3625                                 goto fail;
3626                         t->modifiers [pos].required = 1;
3627                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3628                         pos ++;
3629                 }
3630         }
3631         if (modopt) {
3632                 for (i = 0; i < mono_array_length (modopt); ++i) {
3633                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3634                         if (!is_ok (error))
3635                                 goto fail;
3636                         t->modifiers [pos].required = 0;
3637                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638                         pos ++;
3639                 }
3640         }
3641
3642         return t;
3643 fail:
3644         g_free (t);
3645         return NULL;
3646 }
3647
3648 static void
3649 init_type_builder_generics (MonoObject *type)
3650 {
3651         MonoReflectionTypeBuilder *tb;
3652
3653         if (!is_sre_type_builder(mono_object_class (type)))
3654                 return;
3655         tb = (MonoReflectionTypeBuilder *)type;
3656
3657         if (tb && tb->generic_container)
3658                 mono_reflection_create_generic_class (tb);
3659 }
3660
3661 static guint32
3662 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3663 {
3664         MonoDynamicTable *table;
3665         MonoType *custom = NULL, *type;
3666         guint32 *values;
3667         guint32 token, pclass, parent, sig;
3668         gchar *name;
3669
3670         mono_error_init (error);
3671
3672         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3673         if (token)
3674                 return token;
3675
3676         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3677         return_val_if_nok (error, 0);
3678         /* FIXME: is this call necessary? */
3679         mono_class_from_mono_type (typeb);
3680
3681         /*FIXME this is one more layer of ugliness due how types are created.*/
3682         init_type_builder_generics (fb->type);
3683
3684         /* fb->type does not include the custom modifiers */
3685         /* FIXME: We should do this in one place when a fieldbuilder is created */
3686         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3687         return_val_if_nok (error, 0);
3688
3689         if (fb->modreq || fb->modopt) {
3690                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3691                 return_val_if_nok (error, 0);
3692         }
3693
3694         sig = fieldref_encode_signature (assembly, NULL, type);
3695         g_free (custom);
3696
3697         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3698         return_val_if_nok (error, 0);
3699         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3700         
3701         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3702         parent >>= MONO_TYPEDEFORREF_BITS;
3703
3704         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3705
3706         name = mono_string_to_utf8 (fb->name);
3707
3708         if (assembly->save) {
3709                 alloc_table (table, table->rows + 1);
3710                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3711                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3712                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3713                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3714         }
3715
3716         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3717         table->next_idx ++;
3718         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3719         g_free (name);
3720         return token;
3721 }
3722
3723 static guint32
3724 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3725 {
3726         SigBuffer buf;
3727         guint32 nargs;
3728         guint32 i, idx;
3729
3730         mono_error_init (error);
3731
3732         if (!assembly->save)
3733                 return 0;
3734
3735         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3736         g_assert (helper->type == 2);
3737
3738         if (helper->arguments)
3739                 nargs = mono_array_length (helper->arguments);
3740         else
3741                 nargs = 0;
3742
3743         sigbuffer_init (&buf, 32);
3744
3745         /* Encode calling convention */
3746         /* Change Any to Standard */
3747         if ((helper->call_conv & 0x03) == 0x03)
3748                 helper->call_conv = 0x01;
3749         /* explicit_this implies has_this */
3750         if (helper->call_conv & 0x40)
3751                 helper->call_conv &= 0x20;
3752
3753         if (helper->call_conv == 0) { /* Unmanaged */
3754                 idx = helper->unmanaged_call_conv - 1;
3755         } else {
3756                 /* Managed */
3757                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3758                 if (helper->call_conv & 0x02) /* varargs */
3759                         idx += 0x05;
3760         }
3761
3762         sigbuffer_add_byte (&buf, idx);
3763         sigbuffer_add_value (&buf, nargs);
3764         encode_reflection_type (assembly, helper->return_type, &buf, error);
3765         if (!is_ok (error))
3766                 goto fail;
3767         for (i = 0; i < nargs; ++i) {
3768                 MonoArray *modreqs = NULL;
3769                 MonoArray *modopts = NULL;
3770                 MonoReflectionType *pt;
3771
3772                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3773                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3774                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3775                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3776
3777                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3778                 if (!is_ok (error))
3779                         goto fail;
3780                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3781                 encode_reflection_type (assembly, pt, &buf, error);
3782                 if (!is_ok (error))
3783                         goto fail;
3784         }
3785         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3786         sigbuffer_free (&buf);
3787
3788         return idx;
3789 fail:
3790         sigbuffer_free (&buf);
3791         return 0;
3792 }
3793
3794 static guint32 
3795 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3796 {
3797         guint32 idx;
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800
3801         mono_error_init (error);
3802
3803         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3804         idx = table->next_idx ++;
3805         table->rows ++;
3806         alloc_table (table, table->rows);
3807         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3808
3809         values [MONO_STAND_ALONE_SIGNATURE] =
3810                 mono_reflection_encode_sighelper (assembly, helper, error);
3811         return_val_if_nok (error, 0);
3812         
3813         return idx;
3814 }
3815
3816 static int
3817 reflection_cc_to_file (int call_conv) {
3818         switch (call_conv & 0x3) {
3819         case 0:
3820         case 1: return MONO_CALL_DEFAULT;
3821         case 2: return MONO_CALL_VARARG;
3822         default:
3823                 g_assert_not_reached ();
3824         }
3825         return 0;
3826 }
3827 #endif /* !DISABLE_REFLECTION_EMIT */
3828
3829 typedef struct {
3830         MonoType *parent;
3831         MonoMethodSignature *sig;
3832         char *name;
3833         guint32 token;
3834 } ArrayMethod;
3835
3836 #ifndef DISABLE_REFLECTION_EMIT
3837 static guint32
3838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m, MonoError *error)
3839 {
3840         guint32 nparams, i;
3841         GList *tmp;
3842         char *name = NULL;
3843         MonoMethodSignature *sig;
3844         ArrayMethod *am = NULL;
3845         MonoType *mtype;
3846
3847         mono_error_init (error);
3848
3849         nparams = mono_array_length (m->parameters);
3850         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3851         sig->hasthis = 1;
3852         sig->sentinelpos = -1;
3853         sig->call_convention = reflection_cc_to_file (m->call_conv);
3854         sig->param_count = nparams;
3855         if (m->ret) {
3856                 sig->ret = mono_reflection_type_get_handle (m->ret, error);
3857                 if (!is_ok (error))
3858                         goto fail;
3859         } else
3860                 sig->ret = &mono_defaults.void_class->byval_arg;
3861
3862         mtype = mono_reflection_type_get_handle (m->parent, error);
3863         if (!is_ok (error))
3864                 goto fail;
3865
3866         for (i = 0; i < nparams; ++i) {
3867                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, error);
3868                 if (!is_ok (error))
3869                         goto fail;
3870         }
3871
3872         name = mono_string_to_utf8 (m->name);
3873         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3874                 am = (ArrayMethod *)tmp->data;
3875                 if (strcmp (name, am->name) == 0 && 
3876                                 mono_metadata_type_equal (am->parent, mtype) &&
3877                                 mono_metadata_signature_equal (am->sig, sig)) {
3878                         g_free (name);
3879                         g_free (sig);
3880                         m->table_idx = am->token & 0xffffff;
3881                         return am->token;
3882                 }
3883         }
3884         am = g_new0 (ArrayMethod, 1);
3885         am->name = name;
3886         am->sig = sig;
3887         am->parent = mtype;
3888         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3889                 method_encode_signature (assembly, sig));
3890         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3891         m->table_idx = am->token & 0xffffff;
3892         return am->token;
3893 fail:
3894         g_free (am);
3895         g_free (name);
3896         g_free (sig);
3897         return 0;
3898
3899 }
3900
3901 /*
3902  * Insert into the metadata tables all the info about the TypeBuilder tb.
3903  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3904  */
3905 static gboolean
3906 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3907 {
3908         MonoDynamicTable *table;
3909         guint *values;
3910         int i, is_object = 0, is_system = 0;
3911         char *n;
3912
3913         mono_error_init (error);
3914
3915         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3916         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3917         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3918         n = mono_string_to_utf8 (tb->name);
3919         if (strcmp (n, "Object") == 0)
3920                 is_object++;
3921         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3922         g_free (n);
3923         n = mono_string_to_utf8 (tb->nspace);
3924         if (strcmp (n, "System") == 0)
3925                 is_system++;
3926         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3927         g_free (n);
3928         if (tb->parent && !(is_system && is_object) && 
3929                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3930                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3931                 return_val_if_nok (error, FALSE);
3932                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3933         } else {
3934                 values [MONO_TYPEDEF_EXTENDS] = 0;
3935         }
3936         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3937         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3938
3939         /*
3940          * if we have explicitlayout or sequentiallayouts, output data in the
3941          * ClassLayout table.
3942          */
3943         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3944                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3945                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3946                 table->rows++;
3947                 alloc_table (table, table->rows);
3948                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3949                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3950                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3951                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3952         }
3953
3954         /* handle interfaces */
3955         if (tb->interfaces) {
3956                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3957                 i = table->rows;
3958                 table->rows += mono_array_length (tb->interfaces);
3959                 alloc_table (table, table->rows);
3960                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3961                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3962                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3963                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3964                         return_val_if_nok (error, FALSE);
3965                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3966                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3967                         values += MONO_INTERFACEIMPL_SIZE;
3968                 }
3969         }
3970
3971         /* handle fields */
3972         if (tb->fields) {
3973                 table = &assembly->tables [MONO_TABLE_FIELD];
3974                 table->rows += tb->num_fields;
3975                 alloc_table (table, table->rows);
3976                 for (i = 0; i < tb->num_fields; ++i) {
3977                         mono_image_get_field_info (
3978                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3979                         return_val_if_nok (error, FALSE);
3980                 }
3981         }
3982
3983         /* handle constructors */
3984         if (tb->ctors) {
3985                 table = &assembly->tables [MONO_TABLE_METHOD];
3986                 table->rows += mono_array_length (tb->ctors);
3987                 alloc_table (table, table->rows);
3988                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3989                         if (!mono_image_get_ctor_info (domain,
3990                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3991                                                        assembly, error))
3992                                 return FALSE;
3993                 }
3994         }
3995
3996         /* handle methods */
3997         if (tb->methods) {
3998                 table = &assembly->tables [MONO_TABLE_METHOD];
3999                 table->rows += tb->num_methods;
4000                 alloc_table (table, table->rows);
4001                 for (i = 0; i < tb->num_methods; ++i) {
4002                         if (!mono_image_get_method_info (
4003                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
4004                                 return FALSE;
4005                 }
4006         }
4007
4008         /* Do the same with properties etc.. */
4009         if (tb->events && mono_array_length (tb->events)) {
4010                 table = &assembly->tables [MONO_TABLE_EVENT];
4011                 table->rows += mono_array_length (tb->events);
4012                 alloc_table (table, table->rows);
4013                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4014                 table->rows ++;
4015                 alloc_table (table, table->rows);
4016                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4017                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4018                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4019                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4020                         mono_image_get_event_info (
4021                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4022                         return_val_if_nok (error, FALSE);
4023                 }
4024         }
4025         if (tb->properties && mono_array_length (tb->properties)) {
4026                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4027                 table->rows += mono_array_length (tb->properties);
4028                 alloc_table (table, table->rows);
4029                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4030                 table->rows ++;
4031                 alloc_table (table, table->rows);
4032                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4033                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4034                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4035                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4036                         mono_image_get_property_info (
4037                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4038                         return_val_if_nok (error, FALSE);
4039                 }
4040         }
4041
4042         /* handle generic parameters */
4043         if (tb->generic_params) {
4044                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4045                 table->rows += mono_array_length (tb->generic_params);
4046                 alloc_table (table, table->rows);
4047                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4048                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4049
4050                         mono_image_get_generic_param_info (
4051                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4052                 }
4053         }
4054
4055         mono_image_add_decl_security (assembly, 
4056                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4057
4058         if (tb->subtypes) {
4059                 MonoDynamicTable *ntable;
4060                 
4061                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4062                 ntable->rows += mono_array_length (tb->subtypes);
4063                 alloc_table (ntable, ntable->rows);
4064                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4065
4066                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4067                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4068
4069                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4070                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4071                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4072                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4073                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4074                                 ntable->next_idx, ntable->rows);*/
4075                         values += MONO_NESTED_CLASS_SIZE;
4076                         ntable->next_idx++;
4077                 }
4078         }
4079
4080         return TRUE;
4081 }
4082 #endif
4083
4084 static void
4085 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4086 {
4087         int i;
4088
4089         mono_ptr_array_append (*types, type);
4090
4091         if (!type->subtypes)
4092                 return;
4093
4094         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4095                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4096                 collect_types (types, subtype);
4097         }
4098 }
4099
4100 static gint
4101 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4102 {
4103         if ((*type1)->table_idx < (*type2)->table_idx)
4104                 return -1;
4105         else
4106                 if ((*type1)->table_idx > (*type2)->table_idx)
4107                         return 1;
4108         else
4109                 return 0;
4110 }
4111
4112 static gboolean
4113 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4114         int i;
4115
4116         mono_error_init (error);
4117         if (!pinfo)
4118                 return TRUE;
4119         for (i = 0; i < mono_array_length (pinfo); ++i) {
4120                 MonoReflectionParamBuilder *pb;
4121                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4122                 if (!pb)
4123                         continue;
4124                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4125                         return FALSE;
4126         }
4127
4128         return TRUE;
4129 }
4130
4131 static gboolean
4132 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4133         int i;
4134
4135         mono_error_init (error);
4136         
4137         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4138                 return FALSE;
4139         if (tb->fields) {
4140                 for (i = 0; i < tb->num_fields; ++i) {
4141                         MonoReflectionFieldBuilder* fb;
4142                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4143                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4144                                 return FALSE;
4145                 }
4146         }
4147         if (tb->events) {
4148                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4149                         MonoReflectionEventBuilder* eb;
4150                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4151                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4152                                 return FALSE;
4153                 }
4154         }
4155         if (tb->properties) {
4156                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4157                         MonoReflectionPropertyBuilder* pb;
4158                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4159                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4160                                 return FALSE;
4161                 }
4162         }
4163         if (tb->ctors) {
4164                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4165                         MonoReflectionCtorBuilder* cb;
4166                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4167                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4168                             !params_add_cattrs (assembly, cb->pinfo, error))
4169                                 return FALSE;
4170                 }
4171         }
4172
4173         if (tb->methods) {
4174                 for (i = 0; i < tb->num_methods; ++i) {
4175                         MonoReflectionMethodBuilder* mb;
4176                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4177                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4178                             !params_add_cattrs (assembly, mb->pinfo, error))
4179                                 return FALSE;
4180                 }
4181         }
4182
4183         if (tb->subtypes) {
4184                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4185                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4186                                 return FALSE;
4187                 }
4188         }
4189
4190         return TRUE;
4191 }
4192
4193 static gboolean
4194 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4195 {
4196         int i;
4197         
4198         mono_error_init (error);
4199
4200         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4201                 return FALSE;
4202
4203         if (moduleb->global_methods) {
4204                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4205                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4206                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4207                             !params_add_cattrs (assembly, mb->pinfo, error))
4208                                 return FALSE;
4209                 }
4210         }
4211
4212         if (moduleb->global_fields) {
4213                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4214                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4215                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4216                                 return FALSE;
4217                 }
4218         }
4219         
4220         if (moduleb->types) {
4221                 for (i = 0; i < moduleb->num_types; ++i) {
4222                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4223                                 return FALSE;
4224                 }
4225         }
4226
4227         return TRUE;
4228 }
4229
4230 static void
4231 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4232 {
4233         MonoDynamicTable *table;
4234         guint32 *values;
4235         char blob_size [6];
4236         guchar hash [20];
4237         char *b = blob_size;
4238         char *dir, *path;
4239
4240         table = &assembly->tables [MONO_TABLE_FILE];
4241         table->rows++;
4242         alloc_table (table, table->rows);
4243         values = table->values + table->next_idx * MONO_FILE_SIZE;
4244         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4245         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4246         if (image_is_dynamic (module->image)) {
4247                 /* This depends on the fact that the main module is emitted last */
4248                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4249                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4250         } else {
4251                 dir = NULL;
4252                 path = g_strdup (module->image->name);
4253         }
4254         mono_sha1_get_digest_from_file (path, hash);
4255         g_free (dir);
4256         g_free (path);
4257         mono_metadata_encode_value (20, b, &b);
4258         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4259         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4260         table->next_idx ++;
4261 }
4262
4263 static void
4264 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4265 {
4266         MonoDynamicTable *table;
4267         int i;
4268
4269         table = &assembly->tables [MONO_TABLE_MODULE];
4270         mb->table_idx = table->next_idx ++;
4271         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4272         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4273         i /= 16;
4274         ++i;
4275         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4276         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4277         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4278         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4279 }
4280
4281 static guint32
4282 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4283         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4284 {
4285         MonoDynamicTable *table;
4286         guint32 *values;
4287         guint32 visib, res;
4288
4289         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4290         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4291                 return 0;
4292
4293         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4294         table->rows++;
4295         alloc_table (table, table->rows);
4296         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4297
4298         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4299         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4300         if (klass->nested_in)
4301                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4302         else
4303                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4304         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4305         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4306
4307         res = table->next_idx;
4308
4309         table->next_idx ++;
4310
4311         /* Emit nested types */
4312         if (klass->ext && klass->ext->nested_classes) {
4313                 GList *tmp;
4314
4315                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4316                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4317         }
4318
4319         return res;
4320 }
4321
4322 static void
4323 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4324                               guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly,
4325                               MonoError *error)
4326 {
4327         MonoClass *klass;
4328         guint32 idx, i;
4329
4330         mono_error_init (error);
4331
4332         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4333         return_if_nok (error);
4334
4335         klass = mono_class_from_mono_type (t);
4336
4337         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4338
4339         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4340                                                                                                    parent_index, assembly);
4341
4342         /* 
4343          * Emit nested types
4344          * We need to do this ourselves since klass->nested_classes is not set up.
4345          */
4346         if (tb->subtypes) {
4347                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4348                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly, error);
4349                         return_if_nok (error);
4350                 }
4351         }
4352 }
4353
4354 static void
4355 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4356         guint32 module_index, MonoDynamicImage *assembly)
4357 {
4358         MonoImage *image = module->image;
4359         MonoTableInfo  *t;
4360         guint32 i;
4361
4362         t = &image->tables [MONO_TABLE_TYPEDEF];
4363
4364         for (i = 0; i < t->rows; ++i) {
4365                 MonoError error;
4366                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4367                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4368
4369                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4370                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4371         }
4372 }
4373
4374 static void
4375 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4376 {
4377         MonoDynamicTable *table;
4378         guint32 *values;
4379         guint32 scope, scope_idx, impl, current_idx;
4380         gboolean forwarder = TRUE;
4381         gpointer iter = NULL;
4382         MonoClass *nested;
4383
4384         if (klass->nested_in) {
4385                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4386                 forwarder = FALSE;
4387         } else {
4388                 scope = resolution_scope_from_image (assembly, klass->image);
4389                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4390                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4391                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4392         }
4393
4394         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4395
4396         table->rows++;
4397         alloc_table (table, table->rows);
4398         current_idx = table->next_idx;
4399         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4400
4401         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4402         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4403         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4404         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4405         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4406
4407         table->next_idx++;
4408
4409         while ((nested = mono_class_get_nested_types (klass, &iter)))
4410                 add_exported_type (assemblyb, assembly, nested, current_idx);
4411 }
4412
4413 static void
4414 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4415 {
4416         MonoError error;
4417         MonoClass *klass;
4418         int i;
4419
4420         if (!assemblyb->type_forwarders)
4421                 return;
4422
4423         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4424                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4425                 MonoType *type;
4426                 if (!t)
4427                         continue;
4428
4429                 type = mono_reflection_type_get_handle (t, &error);
4430                 mono_error_assert_ok (&error);
4431                 g_assert (type);
4432
4433                 klass = mono_class_from_mono_type (type);
4434
4435                 add_exported_type (assemblyb, assembly, klass, 0);
4436         }
4437 }
4438
4439 #define align_pointer(base,p)\
4440         do {\
4441                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4442                 if (__diff & 3)\
4443                         (p) += 4 - (__diff & 3);\
4444         } while (0)
4445
4446 static int
4447 compare_constants (const void *a, const void *b)
4448 {
4449         const guint32 *a_values = (const guint32 *)a;
4450         const guint32 *b_values = (const guint32 *)b;
4451         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4452 }
4453
4454 static int
4455 compare_semantics (const void *a, const void *b)
4456 {
4457         const guint32 *a_values = (const guint32 *)a;
4458         const guint32 *b_values = (const guint32 *)b;
4459         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4460         if (assoc)
4461                 return assoc;
4462         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4463 }
4464
4465 static int
4466 compare_custom_attrs (const void *a, const void *b)
4467 {
4468         const guint32 *a_values = (const guint32 *)a;
4469         const guint32 *b_values = (const guint32 *)b;
4470
4471         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4472 }
4473
4474 static int
4475 compare_field_marshal (const void *a, const void *b)
4476 {
4477         const guint32 *a_values = (const guint32 *)a;
4478         const guint32 *b_values = (const guint32 *)b;
4479
4480         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4481 }
4482
4483 static int
4484 compare_nested (const void *a, const void *b)
4485 {
4486         const guint32 *a_values = (const guint32 *)a;
4487         const guint32 *b_values = (const guint32 *)b;
4488
4489         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4490 }
4491
4492 static int
4493 compare_genericparam (const void *a, const void *b)
4494 {
4495         MonoError error;
4496         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4497         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4498
4499         if ((*b_entry)->owner == (*a_entry)->owner) {
4500                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4501                 mono_error_assert_ok (&error);
4502                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4503                 mono_error_assert_ok (&error);
4504                 return 
4505                         mono_type_get_generic_param_num (a_type) -
4506                         mono_type_get_generic_param_num (b_type);
4507         } else
4508                 return (*a_entry)->owner - (*b_entry)->owner;
4509 }
4510
4511 static int
4512 compare_declsecurity_attrs (const void *a, const void *b)
4513 {
4514         const guint32 *a_values = (const guint32 *)a;
4515         const guint32 *b_values = (const guint32 *)b;
4516
4517         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4518 }
4519
4520 static int
4521 compare_interface_impl (const void *a, const void *b)
4522 {
4523         const guint32 *a_values = (const guint32 *)a;
4524         const guint32 *b_values = (const guint32 *)b;
4525
4526         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4527         if (klass)
4528                 return klass;
4529
4530         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4531 }
4532
4533 static void
4534 pad_heap (MonoDynamicStream *sh)
4535 {
4536         if (sh->index & 3) {
4537                 int sz = 4 - (sh->index & 3);
4538                 memset (sh->data + sh->index, 0, sz);
4539                 sh->index += sz;
4540         }
4541 }
4542
4543 struct StreamDesc {
4544         const char *name;
4545         MonoDynamicStream *stream;
4546 };
4547
4548 /*
4549  * build_compressed_metadata() fills in the blob of data that represents the 
4550  * raw metadata as it will be saved in the PE file. The five streams are output 
4551  * and the metadata tables are comnpressed from the guint32 array representation, 
4552  * to the compressed on-disk format.
4553  */
4554 static gboolean
4555 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4556 {
4557         MonoDynamicTable *table;
4558         int i;
4559         guint64 valid_mask = 0;
4560         guint64 sorted_mask;
4561         guint32 heapt_size = 0;
4562         guint32 meta_size = 256; /* allow for header and other stuff */
4563         guint32 table_offset;
4564         guint32 ntables = 0;
4565         guint64 *int64val;
4566         guint32 *int32val;
4567         guint16 *int16val;
4568         MonoImage *meta;
4569         unsigned char *p;
4570         struct StreamDesc stream_desc [5];
4571
4572         mono_error_init (error);
4573
4574         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4575         for (i = 0; i < assembly->gen_params->len; i++) {
4576                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4577                 if (!write_generic_param_entry (assembly, entry, error))
4578                         return FALSE;
4579         }
4580
4581         stream_desc [0].name  = "#~";
4582         stream_desc [0].stream = &assembly->tstream;
4583         stream_desc [1].name  = "#Strings";
4584         stream_desc [1].stream = &assembly->sheap;
4585         stream_desc [2].name  = "#US";
4586         stream_desc [2].stream = &assembly->us;
4587         stream_desc [3].name  = "#Blob";
4588         stream_desc [3].stream = &assembly->blob;
4589         stream_desc [4].name  = "#GUID";
4590         stream_desc [4].stream = &assembly->guid;
4591         
4592         /* tables that are sorted */
4593         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4594                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4595                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4596                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4597                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4598                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4599                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4600         
4601         /* Compute table sizes */
4602         /* the MonoImage has already been created in mono_image_basic_init() */
4603         meta = &assembly->image;
4604
4605         /* sizes should be multiple of 4 */
4606         pad_heap (&assembly->blob);
4607         pad_heap (&assembly->guid);
4608         pad_heap (&assembly->sheap);
4609         pad_heap (&assembly->us);
4610
4611         /* Setup the info used by compute_sizes () */
4612         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4613         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4614         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4615
4616         meta_size += assembly->blob.index;
4617         meta_size += assembly->guid.index;
4618         meta_size += assembly->sheap.index;
4619         meta_size += assembly->us.index;
4620
4621         for (i=0; i < MONO_TABLE_NUM; ++i)
4622                 meta->tables [i].rows = assembly->tables [i].rows;
4623         
4624         for (i = 0; i < MONO_TABLE_NUM; i++){
4625                 if (meta->tables [i].rows == 0)
4626                         continue;
4627                 valid_mask |= (guint64)1 << i;
4628                 ntables ++;
4629                 meta->tables [i].row_size = mono_metadata_compute_size (
4630                         meta, i, &meta->tables [i].size_bitfield);
4631                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4632         }
4633         heapt_size += 24; /* #~ header size */
4634         heapt_size += ntables * 4;
4635         /* make multiple of 4 */
4636         heapt_size += 3;
4637         heapt_size &= ~3;
4638         meta_size += heapt_size;
4639         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4640         p = (unsigned char*)meta->raw_metadata;
4641         /* the metadata signature */
4642         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4643         /* version numbers and 4 bytes reserved */
4644         int16val = (guint16*)p;
4645         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4646         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4647         p += 8;
4648         /* version string */
4649         int32val = (guint32*)p;
4650         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4651         p += 4;
4652         memcpy (p, meta->version, strlen (meta->version));
4653         p += GUINT32_FROM_LE (*int32val);
4654         align_pointer (meta->raw_metadata, p);
4655         int16val = (guint16*)p;
4656         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4657         *int16val = GUINT16_TO_LE (5); /* number of streams */
4658         p += 4;
4659
4660         /*
4661          * write the stream info.
4662          */
4663         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4664         table_offset += 3; table_offset &= ~3;
4665
4666         assembly->tstream.index = heapt_size;
4667         for (i = 0; i < 5; ++i) {
4668                 int32val = (guint32*)p;
4669                 stream_desc [i].stream->offset = table_offset;
4670                 *int32val++ = GUINT32_TO_LE (table_offset);
4671                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4672                 table_offset += GUINT32_FROM_LE (*int32val);
4673                 table_offset += 3; table_offset &= ~3;
4674                 p += 8;
4675                 strcpy ((char*)p, stream_desc [i].name);
4676                 p += strlen (stream_desc [i].name) + 1;
4677                 align_pointer (meta->raw_metadata, p);
4678         }
4679         /* 
4680          * now copy the data, the table stream header and contents goes first.
4681          */
4682         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4683         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4684         int32val = (guint32*)p;
4685         *int32val = GUINT32_TO_LE (0); /* reserved */
4686         p += 4;
4687
4688         *p++ = 2; /* version */
4689         *p++ = 0;
4690
4691         if (meta->idx_string_wide)
4692                 *p |= 0x01;
4693         if (meta->idx_guid_wide)
4694                 *p |= 0x02;
4695         if (meta->idx_blob_wide)
4696                 *p |= 0x04;
4697         ++p;
4698         *p++ = 1; /* reserved */
4699         int64val = (guint64*)p;
4700         *int64val++ = GUINT64_TO_LE (valid_mask);
4701         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4702         p += 16;
4703         int32val = (guint32*)p;
4704         for (i = 0; i < MONO_TABLE_NUM; i++){
4705                 if (meta->tables [i].rows == 0)
4706                         continue;
4707                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4708         }
4709         p = (unsigned char*)int32val;
4710
4711         /* sort the tables that still need sorting */
4712         table = &assembly->tables [MONO_TABLE_CONSTANT];
4713         if (table->rows)
4714                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4715         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4716         if (table->rows)
4717                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4718         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4719         if (table->rows)
4720                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4721         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4722         if (table->rows)
4723                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4724         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4725         if (table->rows)
4726                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4727         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4728         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4729         if (table->rows)
4730                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4731         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4732         if (table->rows)
4733                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4734
4735         /* compress the tables */
4736         for (i = 0; i < MONO_TABLE_NUM; i++){
4737                 int row, col;
4738                 guint32 *values;
4739                 guint32 bitfield = meta->tables [i].size_bitfield;
4740                 if (!meta->tables [i].rows)
4741                         continue;
4742                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4743                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4744                 meta->tables [i].base = (char*)p;
4745                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4746                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4747                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4748                                 switch (mono_metadata_table_size (bitfield, col)) {
4749                                 case 1:
4750                                         *p++ = values [col];
4751                                         break;
4752                                 case 2:
4753                                         *p++ = values [col] & 0xff;
4754                                         *p++ = (values [col] >> 8) & 0xff;
4755                                         break;
4756                                 case 4:
4757                                         *p++ = values [col] & 0xff;
4758                                         *p++ = (values [col] >> 8) & 0xff;
4759                                         *p++ = (values [col] >> 16) & 0xff;
4760                                         *p++ = (values [col] >> 24) & 0xff;
4761                                         break;
4762                                 default:
4763                                         g_assert_not_reached ();
4764                                 }
4765                         }
4766                 }
4767                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4768         }
4769         
4770         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4771         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4772         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4773         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4774         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4775
4776         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4777
4778         return TRUE;
4779 }
4780
4781 /*
4782  * Some tables in metadata need to be sorted according to some criteria, but
4783  * when methods and fields are first created with reflection, they may be assigned a token
4784  * that doesn't correspond to the final token they will get assigned after the sorting.
4785  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4786  * with the reflection objects that represent them. Once all the tables are set up, the 
4787  * reflection objects will contains the correct table index. fixup_method() will fixup the
4788  * tokens for the method with ILGenerator @ilgen.
4789  */
4790 static void
4791 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4792 {
4793         guint32 code_idx = GPOINTER_TO_UINT (value);
4794         MonoReflectionILTokenInfo *iltoken;
4795         MonoReflectionFieldBuilder *field;
4796         MonoReflectionCtorBuilder *ctor;
4797         MonoReflectionMethodBuilder *method;
4798         MonoReflectionTypeBuilder *tb;
4799         MonoReflectionArrayMethod *am;
4800         guint32 i, idx = 0;
4801         unsigned char *target;
4802
4803         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4804                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4805                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4806                 switch (target [3]) {
4807                 case MONO_TABLE_FIELD:
4808                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4809                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4810                                 idx = field->table_idx;
4811                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4812                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4813                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4814                         } else {
4815                                 g_assert_not_reached ();
4816                         }
4817                         break;
4818                 case MONO_TABLE_METHOD:
4819                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4820                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4821                                 idx = method->table_idx;
4822                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4823                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4824                                 idx = ctor->table_idx;
4825                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4826                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4827                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4828                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4829                         } else {
4830                                 g_assert_not_reached ();
4831                         }
4832                         break;
4833                 case MONO_TABLE_TYPEDEF:
4834                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4835                                 g_assert_not_reached ();
4836                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4837                         idx = tb->table_idx;
4838                         break;
4839                 case MONO_TABLE_MEMBERREF:
4840                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4841                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4842                                 idx = am->table_idx;
4843                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4844                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4845                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4846                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4847                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4848                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4849                                 continue;
4850                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4851                                 continue;
4852                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4853                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4854                                 g_assert (is_field_on_inst (f));
4855                                 continue;
4856                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4857                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4858                                 continue;
4859                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4860                                 continue;
4861                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4862                                 continue;
4863                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4864                                 continue;
4865                         } else {
4866                                 g_assert_not_reached ();
4867                         }
4868                         break;
4869                 case MONO_TABLE_METHODSPEC:
4870                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4871                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4872                                 g_assert (mono_method_signature (m)->generic_param_count);
4873                                 continue;
4874                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4875                                 continue;
4876                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4877                                 continue;
4878                         } else {
4879                                 g_assert_not_reached ();
4880                         }
4881                         break;
4882                 default:
4883                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4884                 }
4885                 target [0] = idx & 0xff;
4886                 target [1] = (idx >> 8) & 0xff;
4887                 target [2] = (idx >> 16) & 0xff;
4888         }
4889 }
4890
4891 /*
4892  * fixup_cattrs:
4893  *
4894  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4895  * value is not known when the table is emitted.
4896  */
4897 static void
4898 fixup_cattrs (MonoDynamicImage *assembly)
4899 {
4900         MonoDynamicTable *table;
4901         guint32 *values;
4902         guint32 type, i, idx, token;
4903         MonoObject *ctor;
4904
4905         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4906
4907         for (i = 0; i < table->rows; ++i) {
4908                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4909
4910                 type = values [MONO_CUSTOM_ATTR_TYPE];
4911                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4912                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4913                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4914                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4915                         g_assert (ctor);
4916
4917                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4918                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4919                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4920                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4921                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4922                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4923                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4924                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4925                         }
4926                 }
4927         }
4928 }
4929
4930 static void
4931 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4932 {
4933         MonoDynamicTable *table;
4934         guint32 *values;
4935
4936         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4937         table->rows++;
4938         alloc_table (table, table->rows);
4939         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4940         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4941         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4942         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4943         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4944         table->next_idx++;
4945 }
4946
4947 static void
4948 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4949 {
4950         MonoDynamicTable *table;
4951         guint32 *values;
4952         char blob_size [6];
4953         guchar hash [20];
4954         char *b = blob_size;
4955         char *name, *sname;
4956         guint32 idx, offset;
4957
4958         if (rsrc->filename) {
4959                 name = mono_string_to_utf8 (rsrc->filename);
4960                 sname = g_path_get_basename (name);
4961         
4962                 table = &assembly->tables [MONO_TABLE_FILE];
4963                 table->rows++;
4964                 alloc_table (table, table->rows);
4965                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4966                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4967                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4968                 g_free (sname);
4969
4970                 mono_sha1_get_digest_from_file (name, hash);
4971                 mono_metadata_encode_value (20, b, &b);
4972                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4973                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4974                 g_free (name);
4975                 idx = table->next_idx++;
4976                 rsrc->offset = 0;
4977                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4978         } else {
4979                 char sizebuf [4];
4980                 char *data;
4981                 guint len;
4982                 if (rsrc->data) {
4983                         data = mono_array_addr (rsrc->data, char, 0);
4984                         len = mono_array_length (rsrc->data);
4985                 } else {
4986                         data = NULL;
4987                         len = 0;
4988                 }
4989                 offset = len;
4990                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4991                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4992                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4993                 mono_image_add_stream_data (&assembly->resources, data, len);
4994
4995                 if (!mb->is_main)
4996                         /* 
4997                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4998                          * the main module, but that needs to reference the FILE table
4999                          * which isn't emitted yet.
5000                          */
5001                         return;
5002                 else
5003                         idx = 0;
5004         }
5005
5006         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
5007 }
5008
5009 static void
5010 set_version_from_string (MonoString *version, guint32 *values)
5011 {
5012         gchar *ver, *p, *str;
5013         guint32 i;
5014         
5015         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5016         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5017         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5018         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5019         if (!version)
5020                 return;
5021         ver = str = mono_string_to_utf8 (version);
5022         for (i = 0; i < 4; ++i) {
5023                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5024                 switch (*p) {
5025                 case '.':
5026                         p++;
5027                         break;
5028                 case '*':
5029                         /* handle Revision and Build */
5030                         p++;
5031                         break;
5032                 }
5033                 ver = p;
5034         }
5035         g_free (str);
5036 }
5037
5038 static guint32
5039 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5040         gsize len;
5041         guint32 token = 0;
5042         char blob_size [6];
5043         char *b = blob_size;
5044
5045         if (!pkey)
5046                 return token;
5047
5048         len = mono_array_length (pkey);
5049         mono_metadata_encode_value (len, b, &b);
5050         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5051         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5052
5053         assembly->public_key = (guint8 *)g_malloc (len);
5054         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5055         assembly->public_key_len = len;
5056
5057         /* Special case: check for ECMA key (16 bytes) */
5058         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5059                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5060                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5061         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5062                 /* minimum key size (in 2.0) is 384 bits */
5063                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5064         } else {
5065                 /* FIXME - verifier */
5066                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5067                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5068         }
5069         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5070
5071         return token;
5072 }
5073
5074 static void
5075 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5076 {
5077         MonoError error;
5078         MonoDynamicTable *table;
5079         MonoDynamicImage *assembly;
5080         MonoReflectionAssemblyBuilder *assemblyb;
5081         MonoDomain *domain;
5082         guint32 *values;
5083         int i;
5084         guint32 module_index;
5085
5086         assemblyb = moduleb->assemblyb;
5087         assembly = moduleb->dynamic_image;
5088         domain = mono_object_domain (assemblyb);
5089
5090         /* Emit ASSEMBLY table */
5091         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5092         alloc_table (table, 1);
5093         values = table->values + MONO_ASSEMBLY_SIZE;
5094         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5095         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5096         if (assemblyb->culture) {
5097                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5098         } else {
5099                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5100         }
5101         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5102         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5103         set_version_from_string (assemblyb->version, values);
5104
5105         /* Emit FILE + EXPORTED_TYPE table */
5106         module_index = 0;
5107         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5108                 int j;
5109                 MonoReflectionModuleBuilder *file_module = 
5110                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5111                 if (file_module != moduleb) {
5112                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5113                         module_index ++;
5114                         if (file_module->types) {
5115                                 for (j = 0; j < file_module->num_types; ++j) {
5116                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5117                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly, &error);
5118                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
5119                                 }
5120                         }
5121                 }
5122         }
5123         if (assemblyb->loaded_modules) {
5124                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5125                         MonoReflectionModule *file_module = 
5126                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5127                         mono_image_fill_file_table (domain, file_module, assembly);
5128                         module_index ++;
5129                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5130                 }
5131         }
5132         if (assemblyb->type_forwarders)
5133                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5134
5135         /* Emit MANIFESTRESOURCE table */
5136         module_index = 0;
5137         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5138                 int j;
5139                 MonoReflectionModuleBuilder *file_module = 
5140                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5141                 /* The table for the main module is emitted later */
5142                 if (file_module != moduleb) {
5143                         module_index ++;
5144                         if (file_module->resources) {
5145                                 int len = mono_array_length (file_module->resources);
5146                                 for (j = 0; j < len; ++j) {
5147                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5148                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5149                                 }
5150                         }
5151                 }
5152         }               
5153 }
5154
5155 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5156
5157 /*
5158  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5159  * for the modulebuilder @moduleb.
5160  * At the end of the process, method and field tokens are fixed up and the 
5161  * on-disk compressed metadata representation is created.
5162  * Return TRUE on success, or FALSE on failure and sets @error
5163  */
5164 gboolean
5165 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5166 {
5167         MonoDynamicTable *table;
5168         MonoDynamicImage *assembly;
5169         MonoReflectionAssemblyBuilder *assemblyb;
5170         MonoDomain *domain;
5171         MonoPtrArray types;
5172         guint32 *values;
5173         int i, j;
5174
5175         mono_error_init (error);
5176
5177         assemblyb = moduleb->assemblyb;
5178         assembly = moduleb->dynamic_image;
5179         domain = mono_object_domain (assemblyb);
5180
5181         if (assembly->text_rva)
5182                 return TRUE;
5183
5184         assembly->text_rva = START_TEXT_RVA;
5185
5186         if (moduleb->is_main) {
5187                 mono_image_emit_manifest (moduleb);
5188         }
5189
5190         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5191         table->rows = 1; /* .<Module> */
5192         table->next_idx++;
5193         alloc_table (table, table->rows);
5194         /*
5195          * Set the first entry.
5196          */
5197         values = table->values + table->columns;
5198         values [MONO_TYPEDEF_FLAGS] = 0;
5199         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5200         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5201         values [MONO_TYPEDEF_EXTENDS] = 0;
5202         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5203         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5204
5205         /* 
5206          * handle global methods 
5207          * FIXME: test what to do when global methods are defined in multiple modules.
5208          */
5209         if (moduleb->global_methods) {
5210                 table = &assembly->tables [MONO_TABLE_METHOD];
5211                 table->rows += mono_array_length (moduleb->global_methods);
5212                 alloc_table (table, table->rows);
5213                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5214                         if (!mono_image_get_method_info (
5215                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5216                                 goto leave;
5217                 }
5218         }
5219         if (moduleb->global_fields) {
5220                 table = &assembly->tables [MONO_TABLE_FIELD];
5221                 table->rows += mono_array_length (moduleb->global_fields);
5222                 alloc_table (table, table->rows);
5223                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5224                         mono_image_get_field_info (
5225                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5226                                 error);
5227                         if (!is_ok (error))
5228                                 goto leave;
5229                 }
5230         }
5231
5232         table = &assembly->tables [MONO_TABLE_MODULE];
5233         alloc_table (table, 1);
5234         mono_image_fill_module_table (domain, moduleb, assembly);
5235
5236         /* Collect all types into a list sorted by their table_idx */
5237         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5238
5239         if (moduleb->types)
5240                 for (i = 0; i < moduleb->num_types; ++i) {
5241                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5242                         collect_types (&types, type);
5243                 }
5244
5245         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5246         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5247         table->rows += mono_ptr_array_size (types);
5248         alloc_table (table, table->rows);
5249
5250         /*
5251          * Emit type names + namespaces at one place inside the string heap,
5252          * so load_class_names () needs to touch fewer pages.
5253          */
5254         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5255                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5256                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
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->name);
5261         }
5262
5263         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5264                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5265                 if (!mono_image_get_type_info (domain, type, assembly, error))
5266                         goto leave_types;
5267         }
5268
5269         /* 
5270          * table->rows is already set above and in mono_image_fill_module_table.
5271          */
5272         /* add all the custom attributes at the end, once all the indexes are stable */
5273         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5274                 goto leave_types;
5275
5276         /* CAS assembly permissions */
5277         if (assemblyb->permissions_minimum)
5278                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5279         if (assemblyb->permissions_optional)
5280                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5281         if (assemblyb->permissions_refused)
5282                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5283
5284         if (!module_add_cattrs (assembly, moduleb, error))
5285                 goto leave_types;
5286
5287         /* fixup tokens */
5288         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5289
5290         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5291          * the final tokens and don't need another fixup pass. */
5292
5293         if (moduleb->global_methods) {
5294                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5295                         MonoReflectionMethodBuilder *mb = mono_array_get (
5296                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5297                         if (!mono_image_add_methodimpl (assembly, mb, error))
5298                                 goto leave_types;
5299                 }
5300         }
5301
5302         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5303                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5304                 if (type->methods) {
5305                         for (j = 0; j < type->num_methods; ++j) {
5306                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5307                                         type->methods, MonoReflectionMethodBuilder*, j);
5308
5309                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5310                                         goto leave_types;
5311                         }
5312                 }
5313         }
5314
5315         fixup_cattrs (assembly);
5316
5317 leave_types:
5318         mono_ptr_array_destroy (types);
5319 leave:
5320
5321         return mono_error_ok (error);
5322 }
5323
5324 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5325
5326 gboolean
5327 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5328 {
5329         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5330 }
5331
5332 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5333
5334
5335 typedef struct {
5336         guint32 import_lookup_table;
5337         guint32 timestamp;
5338         guint32 forwarder;
5339         guint32 name_rva;
5340         guint32 import_address_table_rva;
5341 } MonoIDT;
5342
5343 typedef struct {
5344         guint32 name_rva;
5345         guint32 flags;
5346 } MonoILT;
5347
5348 #ifndef DISABLE_REFLECTION_EMIT
5349
5350 /*
5351  * mono_image_insert_string:
5352  * @module: module builder object
5353  * @str: a string
5354  *
5355  * Insert @str into the user string stream of @module.
5356  */
5357 guint32
5358 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5359 {
5360         MonoDynamicImage *assembly;
5361         guint32 idx;
5362         char buf [16];
5363         char *b = buf;
5364         
5365         if (!module->dynamic_image)
5366                 mono_image_module_basic_init (module);
5367
5368         assembly = module->dynamic_image;
5369         
5370         if (assembly->save) {
5371                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5372                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5373 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5374         {
5375                 char *swapped = g_malloc (2 * mono_string_length (str));
5376                 const char *p = (const char*)mono_string_chars (str);
5377
5378                 swap_with_size (swapped, p, 2, mono_string_length (str));
5379                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5380                 g_free (swapped);
5381         }
5382 #else
5383                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5384 #endif
5385                 mono_image_add_stream_data (&assembly->us, "", 1);
5386         } else {
5387                 idx = assembly->us.index ++;
5388         }
5389
5390         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5391
5392         return MONO_TOKEN_STRING | idx;
5393 }
5394
5395 guint32
5396 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5397 {
5398         MonoClass *klass;
5399         guint32 token = 0;
5400         MonoMethodSignature *sig;
5401
5402         mono_error_init (error);
5403
5404         klass = obj->vtable->klass;
5405         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5406                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5407                 MonoMethodSignature *old;
5408                 guint32 sig_token, parent;
5409                 int nargs, i;
5410
5411                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5412
5413                 nargs = mono_array_length (opt_param_types);
5414                 old = mono_method_signature (method);
5415                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5416
5417                 sig->hasthis = old->hasthis;
5418                 sig->explicit_this = old->explicit_this;
5419                 sig->call_convention = old->call_convention;
5420                 sig->generic_param_count = old->generic_param_count;
5421                 sig->param_count = old->param_count + nargs;
5422                 sig->sentinelpos = old->param_count;
5423                 sig->ret = old->ret;
5424
5425                 for (i = 0; i < old->param_count; i++)
5426                         sig->params [i] = old->params [i];
5427
5428                 for (i = 0; i < nargs; i++) {
5429                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5430                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5431                         if (!is_ok (error)) goto fail;
5432                 }
5433
5434                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5435                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5436                 parent >>= MONO_TYPEDEFORREF_BITS;
5437
5438                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5439                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5440
5441                 sig_token = method_encode_signature (assembly, sig);
5442                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5443         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5444                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5445                 ReflectionMethodBuilder rmb;
5446                 guint32 parent, sig_token;
5447                 int nopt_args, nparams, ngparams, i;
5448
5449                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5450                         goto fail;
5451                 
5452                 rmb.opt_types = opt_param_types;
5453                 nopt_args = mono_array_length (opt_param_types);
5454
5455                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5456                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5457                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5458
5459                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5460                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5461                 sig->call_convention = rmb.call_conv;
5462                 sig->generic_param_count = ngparams;
5463                 sig->param_count = nparams + nopt_args;
5464                 sig->sentinelpos = nparams;
5465                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5466                 if (!is_ok (error)) goto fail;
5467
5468                 for (i = 0; i < nparams; i++) {
5469                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5470                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5471                         if (!is_ok (error)) goto fail;
5472                 }
5473
5474                 for (i = 0; i < nopt_args; i++) {
5475                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5476                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5477                         if (!is_ok (error)) goto fail;
5478                 }
5479
5480                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5481                 if (!is_ok (error))
5482                         goto fail;
5483
5484                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5485                 if (!mono_error_ok (error))
5486                         goto fail;
5487                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5488
5489                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5490                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5491
5492                 char *name = mono_string_to_utf8 (rmb.name);
5493                 token = mono_image_get_varargs_method_token (
5494                         assembly, parent, name, sig_token);
5495                 g_free (name);
5496         } else {
5497                 g_error ("requested method token for %s\n", klass->name);
5498         }
5499
5500         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5501         register_dyn_token (assembly, token, obj);
5502         return token;
5503 fail:
5504         g_assert (!mono_error_ok (error));
5505         return 0;
5506 }
5507
5508 /*
5509  * mono_image_create_token:
5510  * @assembly: a dynamic assembly
5511  * @obj:
5512  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5513  *
5514  * Get a token to insert in the IL code stream for the given MemberInfo.
5515  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5516  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5517  * entry.
5518  */
5519 guint32
5520 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5521                          gboolean create_open_instance, gboolean register_token,
5522                          MonoError *error)
5523 {
5524         MonoClass *klass;
5525         guint32 token = 0;
5526
5527         mono_error_init (error);
5528
5529         klass = obj->vtable->klass;
5530
5531         /* Check for user defined reflection objects */
5532         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5533         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5534                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5535                 return 0;
5536         }
5537
5538         if (strcmp (klass->name, "MethodBuilder") == 0) {
5539                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5540                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5541
5542                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5543                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5544                 else {
5545                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5546                         if (!mono_error_ok (error))
5547                                 return 0;
5548                 }
5549                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5550         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5551                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5552                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5553
5554                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5555                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5556                 else {
5557                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5558                         if (!mono_error_ok (error))
5559                                 return 0;
5560                 }
5561                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5562         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5563                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5564                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5565                 if (tb->generic_params) {
5566                         token = mono_image_get_generic_field_token (assembly, fb, error);
5567                         return_val_if_nok (error, 0);
5568                 } else {
5569                         if (tb->module->dynamic_image == assembly) {
5570                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5571                         } else {
5572                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5573                         }
5574                 }
5575         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5576                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5577                 if (create_open_instance && tb->generic_params) {
5578                         MonoType *type;
5579                         init_type_builder_generics (obj);
5580                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5581                         return_val_if_nok (error, 0);
5582                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5583                         token = mono_metadata_token_from_dor (token);
5584                 } else if (tb->module->dynamic_image == assembly) {
5585                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5586                 } else {
5587                         MonoType *type;
5588                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5589                         return_val_if_nok (error, 0);
5590                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5591                 }
5592         } else if (strcmp (klass->name, "MonoType") == 0) {
5593                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5594                 return_val_if_nok (error, 0);
5595                 MonoClass *mc = mono_class_from_mono_type (type);
5596                 token = mono_metadata_token_from_dor (
5597                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5598         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5599                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5600                 return_val_if_nok (error, 0);
5601                 token = mono_metadata_token_from_dor (
5602                         mono_image_typedef_or_ref (assembly, type));
5603         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5604                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5605                 return_val_if_nok (error, 0);
5606                 token = mono_metadata_token_from_dor (
5607                         mono_image_typedef_or_ref (assembly, type));
5608         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5609                    strcmp (klass->name, "MonoMethod") == 0 ||
5610                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5611                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5612                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5613                 if (m->method->is_inflated) {
5614                         if (create_open_instance)
5615                                 token = mono_image_get_methodspec_token (assembly, m->method);
5616                         else
5617                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5618                 } else if ((m->method->klass->image == &assembly->image) &&
5619                          !m->method->klass->generic_class) {
5620                         static guint32 method_table_idx = 0xffffff;
5621                         if (m->method->klass->wastypebuilder) {
5622                                 /* we use the same token as the one that was assigned
5623                                  * to the Methodbuilder.
5624                                  * FIXME: do the equivalent for Fields.
5625                                  */
5626                                 token = m->method->token;
5627                         } else {
5628                                 /*
5629                                  * Each token should have a unique index, but the indexes are
5630                                  * assigned by managed code, so we don't know about them. An
5631                                  * easy solution is to count backwards...
5632                                  */
5633                                 method_table_idx --;
5634                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5635                         }
5636                 } else {
5637                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5638                 }
5639                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5640         } else if (strcmp (klass->name, "MonoField") == 0) {
5641                 MonoReflectionField *f = (MonoReflectionField *)obj;
5642                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5643                         static guint32 field_table_idx = 0xffffff;
5644                         field_table_idx --;
5645                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5646                 } else {
5647                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5648                 }
5649                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5650         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5651                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5652                 token = mono_image_get_array_token (assembly, m, error);
5653                 return_val_if_nok (error, 0);
5654         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5655                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5656                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5657                 return_val_if_nok (error, 0);
5658         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5659                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5660                 return_val_if_nok (error, 0);
5661                 token = mono_metadata_token_from_dor (
5662                         mono_image_typedef_or_ref (assembly, type));
5663         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5664                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5665                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5666                 return_val_if_nok (error, 0);
5667         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5668                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5669                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5670                 if (!mono_error_ok (error))
5671                         return 0;
5672         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5673                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5674                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5675                 if (!mono_error_ok (error))
5676                         return 0;
5677         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5678                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5679                 return_val_if_nok (error, 0);
5680                 token = mono_metadata_token_from_dor (
5681                                 mono_image_typedef_or_ref (assembly, type));
5682         } else {
5683                 g_error ("requested token for %s\n", klass->name);
5684         }
5685
5686         if (register_token)
5687                 mono_image_register_token (assembly, token, obj);
5688
5689         return token;
5690 }
5691
5692 /*
5693  * mono_image_register_token:
5694  *
5695  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5696  * the Module.ResolveXXXToken () methods to work.
5697  */
5698 void
5699 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5700 {
5701         MonoObject *prev;
5702
5703         dynamic_image_lock (assembly);
5704         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5705         if (prev) {
5706                 /* There could be multiple MethodInfo objects with the same token */
5707                 //g_assert (prev == obj);
5708         } else {
5709                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5710         }
5711         dynamic_image_unlock (assembly);
5712 }
5713
5714 static MonoDynamicImage*
5715 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5716 {
5717         static const guchar entrycode [16] = {0xff, 0x25, 0};
5718         MonoDynamicImage *image;
5719         int i;
5720
5721         const char *version;
5722
5723         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5724                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5725         else
5726                 version = mono_get_runtime_info ()->runtime_version;
5727
5728 #if HAVE_BOEHM_GC
5729         /* The MonoGHashTable's need GC tracking */
5730         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5731 #else
5732         image = g_new0 (MonoDynamicImage, 1);
5733 #endif
5734
5735         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5736         
5737         /*g_print ("created image %p\n", image);*/
5738         /* keep in sync with image.c */
5739         image->image.name = assembly_name;
5740         image->image.assembly_name = image->image.name; /* they may be different */
5741         image->image.module_name = module_name;
5742         image->image.version = g_strdup (version);
5743         image->image.md_version_major = 1;
5744         image->image.md_version_minor = 1;
5745         image->image.dynamic = TRUE;
5746
5747         image->image.references = g_new0 (MonoAssembly*, 1);
5748         image->image.references [0] = NULL;
5749
5750         mono_image_init (&image->image);
5751
5752         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");
5753         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5754         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5755         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5756         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5757         image->handleref = g_hash_table_new (NULL, NULL);
5758         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");
5759         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5760         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");
5761         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");
5762         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5763         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5764         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5765         image->gen_params = g_ptr_array_new ();
5766         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5767
5768         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5769         string_heap_init (&image->sheap);
5770         mono_image_add_stream_data (&image->us, "", 1);
5771         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5772         /* import tables... */
5773         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5774         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5775         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5776         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5777         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5778         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5779         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5780         stream_data_align (&image->code);
5781
5782         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5783
5784         for (i=0; i < MONO_TABLE_NUM; ++i) {
5785                 image->tables [i].next_idx = 1;
5786                 image->tables [i].columns = table_sizes [i];
5787         }
5788
5789         image->image.assembly = (MonoAssembly*)assembly;
5790         image->run = assembly->run;
5791         image->save = assembly->save;
5792         image->pe_kind = 0x1; /* ILOnly */
5793         image->machine = 0x14c; /* I386 */
5794         
5795         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5796
5797         dynamic_images_lock ();
5798
5799         if (!dynamic_images)
5800                 dynamic_images = g_ptr_array_new ();
5801
5802         g_ptr_array_add (dynamic_images, image);
5803
5804         dynamic_images_unlock ();
5805
5806         return image;
5807 }
5808 #endif
5809
5810 static void
5811 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5812 {
5813         g_free (key);
5814 }
5815
5816 static void
5817 release_hashtable (MonoGHashTable **hash)
5818 {
5819         if (*hash) {
5820                 mono_g_hash_table_destroy (*hash);
5821                 *hash = NULL;
5822         }
5823 }
5824
5825 void
5826 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5827 {
5828         release_hashtable (&image->token_fixups);
5829         release_hashtable (&image->handleref_managed);
5830         release_hashtable (&image->tokens);
5831         release_hashtable (&image->remapped_tokens);
5832         release_hashtable (&image->generic_def_objects);
5833         release_hashtable (&image->methodspec);
5834 }
5835
5836 // Free dynamic image pass one: Free resources but not image itself
5837 void
5838 mono_dynamic_image_free (MonoDynamicImage *image)
5839 {
5840         MonoDynamicImage *di = image;
5841         GList *list;
5842         int i;
5843
5844         if (di->methodspec)
5845                 mono_g_hash_table_destroy (di->methodspec);
5846         if (di->typespec)
5847                 g_hash_table_destroy (di->typespec);
5848         if (di->typeref)
5849                 g_hash_table_destroy (di->typeref);
5850         if (di->handleref)
5851                 g_hash_table_destroy (di->handleref);
5852         if (di->handleref_managed)
5853                 mono_g_hash_table_destroy (di->handleref_managed);
5854         if (di->tokens)
5855                 mono_g_hash_table_destroy (di->tokens);
5856         if (di->remapped_tokens)
5857                 mono_g_hash_table_destroy (di->remapped_tokens);
5858         if (di->generic_def_objects)
5859                 mono_g_hash_table_destroy (di->generic_def_objects);
5860         if (di->blob_cache) {
5861                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5862                 g_hash_table_destroy (di->blob_cache);
5863         }
5864         if (di->standalonesig_cache)
5865                 g_hash_table_destroy (di->standalonesig_cache);
5866         for (list = di->array_methods; list; list = list->next) {
5867                 ArrayMethod *am = (ArrayMethod *)list->data;
5868                 g_free (am->sig);
5869                 g_free (am->name);
5870                 g_free (am);
5871         }
5872         g_list_free (di->array_methods);
5873         if (di->gen_params) {
5874                 for (i = 0; i < di->gen_params->len; i++) {
5875                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5876                         mono_gc_deregister_root ((char*) &entry->gparam);
5877                         g_free (entry);
5878                 }
5879                 g_ptr_array_free (di->gen_params, TRUE);
5880         }
5881         if (di->token_fixups)
5882                 mono_g_hash_table_destroy (di->token_fixups);
5883         if (di->method_to_table_idx)
5884                 g_hash_table_destroy (di->method_to_table_idx);
5885         if (di->field_to_table_idx)
5886                 g_hash_table_destroy (di->field_to_table_idx);
5887         if (di->method_aux_hash)
5888                 g_hash_table_destroy (di->method_aux_hash);
5889         if (di->vararg_aux_hash)
5890                 g_hash_table_destroy (di->vararg_aux_hash);
5891         g_free (di->strong_name);
5892         g_free (di->win32_res);
5893         if (di->public_key)
5894                 g_free (di->public_key);
5895
5896         /*g_print ("string heap destroy for image %p\n", di);*/
5897         mono_dynamic_stream_reset (&di->sheap);
5898         mono_dynamic_stream_reset (&di->code);
5899         mono_dynamic_stream_reset (&di->resources);
5900         mono_dynamic_stream_reset (&di->us);
5901         mono_dynamic_stream_reset (&di->blob);
5902         mono_dynamic_stream_reset (&di->tstream);
5903         mono_dynamic_stream_reset (&di->guid);
5904         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5905                 g_free (di->tables [i].values);
5906         }
5907
5908         dynamic_images_lock ();
5909
5910         if (dynamic_images)
5911                 g_ptr_array_remove (dynamic_images, di);
5912
5913         dynamic_images_unlock ();
5914 }
5915
5916 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5917 void
5918 mono_dynamic_image_free_image (MonoDynamicImage *image)
5919 {
5920         /* See create_dynamic_mono_image () */
5921 #if HAVE_BOEHM_GC
5922         /* Allocated using GC_MALLOC */
5923 #else
5924         g_free (image);
5925 #endif
5926 }
5927
5928 #ifndef DISABLE_REFLECTION_EMIT
5929
5930 /*
5931  * mono_image_basic_init:
5932  * @assembly: an assembly builder object
5933  *
5934  * Create the MonoImage that represents the assembly builder and setup some
5935  * of the helper hash table and the basic metadata streams.
5936  */
5937 void
5938 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5939 {
5940         MonoDynamicAssembly *assembly;
5941         MonoDynamicImage *image;
5942         MonoDomain *domain = mono_object_domain (assemblyb);
5943         
5944         if (assemblyb->dynamic_assembly)
5945                 return;
5946
5947 #if HAVE_BOEHM_GC
5948         /* assembly->assembly.image might be GC allocated */
5949         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5950 #else
5951         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5952 #endif
5953
5954         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5955         
5956         assembly->assembly.ref_count = 1;
5957         assembly->assembly.dynamic = TRUE;
5958         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5959         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5960         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5961         if (assemblyb->culture)
5962                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5963         else
5964                 assembly->assembly.aname.culture = g_strdup ("");
5965
5966         if (assemblyb->version) {
5967                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5968                         char **version = g_strsplit (vstr, ".", 4);
5969                         char **parts = version;
5970                         assembly->assembly.aname.major = atoi (*parts++);
5971                         assembly->assembly.aname.minor = atoi (*parts++);
5972                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5973                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5974
5975                         g_strfreev (version);
5976                         g_free (vstr);
5977         } else {
5978                         assembly->assembly.aname.major = 0;
5979                         assembly->assembly.aname.minor = 0;
5980                         assembly->assembly.aname.build = 0;
5981                         assembly->assembly.aname.revision = 0;
5982         }
5983
5984         assembly->run = assemblyb->access != 2;
5985         assembly->save = assemblyb->access != 1;
5986         assembly->domain = domain;
5987
5988         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5989         image->initial_image = TRUE;
5990         assembly->assembly.aname.name = image->image.name;
5991         assembly->assembly.image = &image->image;
5992         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5993                 /* -1 to correct for the trailing NULL byte */
5994                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5995                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5996                 }
5997                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5998         }
5999
6000         mono_domain_assemblies_lock (domain);
6001         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
6002         mono_domain_assemblies_unlock (domain);
6003
6004         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
6005         
6006         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
6007         
6008         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
6009 }
6010
6011 #endif /* !DISABLE_REFLECTION_EMIT */
6012
6013 #ifndef DISABLE_REFLECTION_EMIT_SAVE
6014
6015 static int
6016 calc_section_size (MonoDynamicImage *assembly)
6017 {
6018         int nsections = 0;
6019
6020         /* alignment constraints */
6021         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6022         g_assert ((assembly->code.index % 4) == 0);
6023         assembly->meta_size += 3;
6024         assembly->meta_size &= ~3;
6025         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6026         g_assert ((assembly->resources.index % 4) == 0);
6027
6028         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6029         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6030         nsections++;
6031
6032         if (assembly->win32_res) {
6033                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6034
6035                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6036                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6037                 nsections++;
6038         }
6039
6040         assembly->sections [MONO_SECTION_RELOC].size = 12;
6041         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6042         nsections++;
6043
6044         return nsections;
6045 }
6046
6047 typedef struct {
6048         guint32 id;
6049         guint32 offset;
6050         GSList *children;
6051         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6052 } ResTreeNode;
6053
6054 static int
6055 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6056 {
6057         ResTreeNode *t1 = (ResTreeNode*)a;
6058         ResTreeNode *t2 = (ResTreeNode*)b;
6059
6060         return t1->id - t2->id;
6061 }
6062
6063 /*
6064  * resource_tree_create:
6065  *
6066  *  Organize the resources into a resource tree.
6067  */
6068 static ResTreeNode *
6069 resource_tree_create (MonoArray *win32_resources)
6070 {
6071         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6072         GSList *l;
6073         int i;
6074
6075         tree = g_new0 (ResTreeNode, 1);
6076         
6077         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6078                 MonoReflectionWin32Resource *win32_res =
6079                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6080
6081                 /* Create node */
6082
6083                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6084                 lang_node = g_new0 (ResTreeNode, 1);
6085                 lang_node->id = win32_res->lang_id;
6086                 lang_node->win32_res = win32_res;
6087
6088                 /* Create type node if neccesary */
6089                 type_node = NULL;
6090                 for (l = tree->children; l; l = l->next)
6091                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6092                                 type_node = (ResTreeNode*)l->data;
6093                                 break;
6094                         }
6095
6096                 if (!type_node) {
6097                         type_node = g_new0 (ResTreeNode, 1);
6098                         type_node->id = win32_res->res_type;
6099
6100                         /* 
6101                          * The resource types have to be sorted otherwise
6102                          * Windows Explorer can't display the version information.
6103                          */
6104                         tree->children = g_slist_insert_sorted (tree->children, 
6105                                 type_node, resource_tree_compare_by_id);
6106                 }
6107
6108                 /* Create res node if neccesary */
6109                 res_node = NULL;
6110                 for (l = type_node->children; l; l = l->next)
6111                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6112                                 res_node = (ResTreeNode*)l->data;
6113                                 break;
6114                         }
6115
6116                 if (!res_node) {
6117                         res_node = g_new0 (ResTreeNode, 1);
6118                         res_node->id = win32_res->res_id;
6119                         type_node->children = g_slist_append (type_node->children, res_node);
6120                 }
6121
6122                 res_node->children = g_slist_append (res_node->children, lang_node);
6123         }
6124
6125         return tree;
6126 }
6127
6128 /*
6129  * resource_tree_encode:
6130  * 
6131  *   Encode the resource tree into the format used in the PE file.
6132  */
6133 static void
6134 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6135 {
6136         char *entries;
6137         MonoPEResourceDir dir;
6138         MonoPEResourceDirEntry dir_entry;
6139         MonoPEResourceDataEntry data_entry;
6140         GSList *l;
6141         guint32 res_id_entries;
6142
6143         /*
6144          * For the format of the resource directory, see the article
6145          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6146          * Matt Pietrek
6147          */
6148
6149         memset (&dir, 0, sizeof (dir));
6150         memset (&dir_entry, 0, sizeof (dir_entry));
6151         memset (&data_entry, 0, sizeof (data_entry));
6152
6153         g_assert (sizeof (dir) == 16);
6154         g_assert (sizeof (dir_entry) == 8);
6155         g_assert (sizeof (data_entry) == 16);
6156
6157         node->offset = p - begin;
6158
6159         /* IMAGE_RESOURCE_DIRECTORY */
6160         res_id_entries = g_slist_length (node->children);
6161         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6162
6163         memcpy (p, &dir, sizeof (dir));
6164         p += sizeof (dir);
6165
6166         /* Reserve space for entries */
6167         entries = p;
6168         p += sizeof (dir_entry) * res_id_entries;
6169
6170         /* Write children */
6171         for (l = node->children; l; l = l->next) {
6172                 ResTreeNode *child = (ResTreeNode*)l->data;
6173
6174                 if (child->win32_res) {
6175                         guint32 size;
6176
6177                         child->offset = p - begin;
6178
6179                         /* IMAGE_RESOURCE_DATA_ENTRY */
6180                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6181                         size = mono_array_length (child->win32_res->res_data);
6182                         data_entry.rde_size = GUINT32_TO_LE (size);
6183
6184                         memcpy (p, &data_entry, sizeof (data_entry));
6185                         p += sizeof (data_entry);
6186
6187                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6188                         p += size;
6189                 } else {
6190                         resource_tree_encode (child, begin, p, &p);
6191                 }
6192         }
6193
6194         /* IMAGE_RESOURCE_ENTRY */
6195         for (l = node->children; l; l = l->next) {
6196                 ResTreeNode *child = (ResTreeNode*)l->data;
6197
6198                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6199                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6200
6201                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6202                 entries += sizeof (dir_entry);
6203         }
6204
6205         *endbuf = p;
6206 }
6207
6208 static void
6209 resource_tree_free (ResTreeNode * node)
6210 {
6211         GSList * list;
6212         for (list = node->children; list; list = list->next)
6213                 resource_tree_free ((ResTreeNode*)list->data);
6214         g_slist_free(node->children);
6215         g_free (node);
6216 }
6217
6218 static void
6219 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6220 {
6221         char *buf;
6222         char *p;
6223         guint32 size, i;
6224         MonoReflectionWin32Resource *win32_res;
6225         ResTreeNode *tree;
6226
6227         if (!assemblyb->win32_resources)
6228                 return;
6229
6230         /*
6231          * Resources are stored in a three level tree inside the PE file.
6232          * - level one contains a node for each type of resource
6233          * - level two contains a node for each resource
6234          * - level three contains a node for each instance of a resource for a
6235          *   specific language.
6236          */
6237
6238         tree = resource_tree_create (assemblyb->win32_resources);
6239
6240         /* Estimate the size of the encoded tree */
6241         size = 0;
6242         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6243                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6244                 size += mono_array_length (win32_res->res_data);
6245         }
6246         /* Directory structure */
6247         size += mono_array_length (assemblyb->win32_resources) * 256;
6248         p = buf = (char *)g_malloc (size);
6249
6250         resource_tree_encode (tree, p, p, &p);
6251
6252         g_assert (p - buf <= size);
6253
6254         assembly->win32_res = (char *)g_malloc (p - buf);
6255         assembly->win32_res_size = p - buf;
6256         memcpy (assembly->win32_res, buf, p - buf);
6257
6258         g_free (buf);
6259         resource_tree_free (tree);
6260 }
6261
6262 static void
6263 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6264 {
6265         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6266         int i;
6267
6268         p += sizeof (MonoPEResourceDir);
6269         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6270                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6271                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6272                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6273                         fixup_resource_directory (res_section, child, rva);
6274                 } else {
6275                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6276                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6277                 }
6278
6279                 p += sizeof (MonoPEResourceDirEntry);
6280         }
6281 }
6282
6283 static void
6284 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6285 {
6286         guint32 dummy;
6287         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6288                 g_error ("WriteFile returned %d\n", GetLastError ());
6289 }
6290
6291 /*
6292  * mono_image_create_pefile:
6293  * @mb: a module builder object
6294  * 
6295  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6296  * assembly->pefile where it can be easily retrieved later in chunks.
6297  */
6298 gboolean
6299 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6300 {
6301         MonoMSDOSHeader *msdos;
6302         MonoDotNetHeader *header;
6303         MonoSectionTable *section;
6304         MonoCLIHeader *cli_header;
6305         guint32 size, image_size, virtual_base, text_offset;
6306         guint32 header_start, section_start, file_offset, virtual_offset;
6307         MonoDynamicImage *assembly;
6308         MonoReflectionAssemblyBuilder *assemblyb;
6309         MonoDynamicStream pefile_stream = {0};
6310         MonoDynamicStream *pefile = &pefile_stream;
6311         int i, nsections;
6312         guint32 *rva, value;
6313         guchar *p;
6314         static const unsigned char msheader[] = {
6315                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6316                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6317                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6318                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6319                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6320                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6321                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6322                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6323         };
6324
6325         mono_error_init (error);
6326
6327         assemblyb = mb->assemblyb;
6328
6329         mono_image_basic_init (assemblyb);
6330         assembly = mb->dynamic_image;
6331
6332         assembly->pe_kind = assemblyb->pe_kind;
6333         assembly->machine = assemblyb->machine;
6334         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6335         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6336         
6337         if (!mono_image_build_metadata (mb, error))
6338                 return FALSE;
6339         
6340
6341         if (mb->is_main && assemblyb->resources) {
6342                 int len = mono_array_length (assemblyb->resources);
6343                 for (i = 0; i < len; ++i)
6344                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6345         }
6346
6347         if (mb->resources) {
6348                 int len = mono_array_length (mb->resources);
6349                 for (i = 0; i < len; ++i)
6350                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6351         }
6352
6353         if (!build_compressed_metadata (assembly, error))
6354                 return FALSE;
6355
6356         if (mb->is_main)
6357                 assembly_add_win32_resources (assembly, assemblyb);
6358
6359         nsections = calc_section_size (assembly);
6360         
6361         /* The DOS header and stub */
6362         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6363         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6364
6365         /* the dotnet header */
6366         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6367
6368         /* the section tables */
6369         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6370
6371         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6372         virtual_offset = VIRT_ALIGN;
6373         image_size = 0;
6374
6375         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6376                 if (!assembly->sections [i].size)
6377                         continue;
6378                 /* align offsets */
6379                 file_offset += FILE_ALIGN - 1;
6380                 file_offset &= ~(FILE_ALIGN - 1);
6381                 virtual_offset += VIRT_ALIGN - 1;
6382                 virtual_offset &= ~(VIRT_ALIGN - 1);
6383
6384                 assembly->sections [i].offset = file_offset;
6385                 assembly->sections [i].rva = virtual_offset;
6386
6387                 file_offset += assembly->sections [i].size;
6388                 virtual_offset += assembly->sections [i].size;
6389                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6390         }
6391
6392         file_offset += FILE_ALIGN - 1;
6393         file_offset &= ~(FILE_ALIGN - 1);
6394
6395         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6396
6397         /* back-patch info */
6398         msdos = (MonoMSDOSHeader*)pefile->data;
6399         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6400
6401         header = (MonoDotNetHeader*)(pefile->data + header_start);
6402         header->pesig [0] = 'P';
6403         header->pesig [1] = 'E';
6404         
6405         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6406         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6407         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6408         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6409         if (assemblyb->pekind == 1) {
6410                 /* it's a dll */
6411                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6412         } else {
6413                 /* it's an exe */
6414                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6415         }
6416
6417         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6418
6419         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6420         header->pe.pe_major = 6;
6421         header->pe.pe_minor = 0;
6422         size = assembly->sections [MONO_SECTION_TEXT].size;
6423         size += FILE_ALIGN - 1;
6424         size &= ~(FILE_ALIGN - 1);
6425         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6426         size = assembly->sections [MONO_SECTION_RSRC].size;
6427         size += FILE_ALIGN - 1;
6428         size &= ~(FILE_ALIGN - 1);
6429         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6430         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6431         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6432         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6433         /* pe_rva_entry_point always at the beginning of the text section */
6434         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6435
6436         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6437         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6438         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6439         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6440         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6441         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6442         size = section_start;
6443         size += FILE_ALIGN - 1;
6444         size &= ~(FILE_ALIGN - 1);
6445         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6446         size = image_size;
6447         size += VIRT_ALIGN - 1;
6448         size &= ~(VIRT_ALIGN - 1);
6449         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6450
6451         /*
6452         // Translate the PEFileKind value to the value expected by the Windows loader
6453         */
6454         {
6455                 short kind;
6456
6457                 /*
6458                 // PEFileKinds.Dll == 1
6459                 // PEFileKinds.ConsoleApplication == 2
6460                 // PEFileKinds.WindowApplication == 3
6461                 //
6462                 // need to get:
6463                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6464                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6465                 */
6466                 if (assemblyb->pekind == 3)
6467                         kind = 2;
6468                 else
6469                         kind = 3;
6470                 
6471                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6472         }    
6473         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6474         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6475         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6476         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6477         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6478         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6479
6480         /* fill data directory entries */
6481
6482         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6483         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6484
6485         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6486         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6487
6488         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6489         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6490         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6491         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6492         /* patch entrypoint name */
6493         if (assemblyb->pekind == 1)
6494                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6495         else
6496                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6497         /* patch imported function RVA name */
6498         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6499         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6500
6501         /* the import table */
6502         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6503         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6504         /* patch imported dll RVA name and other entries in the dir */
6505         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6506         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6507         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6508         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6509         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6510         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6511
6512         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6513         value = (assembly->text_rva + assembly->imp_names_offset);
6514         *p++ = (value) & 0xff;
6515         *p++ = (value >> 8) & (0xff);
6516         *p++ = (value >> 16) & (0xff);
6517         *p++ = (value >> 24) & (0xff);
6518
6519         /* the CLI header info */
6520         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6521         cli_header->ch_size = GUINT32_FROM_LE (72);
6522         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6523         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6524         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6525         if (assemblyb->entry_point) {
6526                 guint32 table_idx = 0;
6527                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6528                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6529                         table_idx = methodb->table_idx;
6530                 } else {
6531                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6532                 }
6533                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6534         } else {
6535                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6536         }
6537         /* The embedded managed resources */
6538         text_offset = assembly->text_rva + assembly->code.index;
6539         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6540         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6541         text_offset += assembly->resources.index;
6542         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6543         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6544         text_offset += assembly->meta_size;
6545         if (assembly->strong_name_size) {
6546                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6547                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6548                 text_offset += assembly->strong_name_size;
6549         }
6550
6551         /* write the section tables and section content */
6552         section = (MonoSectionTable*)(pefile->data + section_start);
6553         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6554                 static const char section_names [][7] = {
6555                         ".text", ".rsrc", ".reloc"
6556                 };
6557                 if (!assembly->sections [i].size)
6558                         continue;
6559                 strcpy (section->st_name, section_names [i]);
6560                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6561                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6562                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6563                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6564                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6565                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6566                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6567                 section ++;
6568         }
6569         
6570         checked_write_file (file, pefile->data, pefile->index);
6571         
6572         mono_dynamic_stream_reset (pefile);
6573         
6574         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6575                 if (!assembly->sections [i].size)
6576                         continue;
6577                 
6578                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6579                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6580                 
6581                 switch (i) {
6582                 case MONO_SECTION_TEXT:
6583                         /* patch entry point */
6584                         p = (guchar*)(assembly->code.data + 2);
6585                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6586                         *p++ = (value) & 0xff;
6587                         *p++ = (value >> 8) & 0xff;
6588                         *p++ = (value >> 16) & 0xff;
6589                         *p++ = (value >> 24) & 0xff;
6590                 
6591                         checked_write_file (file, assembly->code.data, assembly->code.index);
6592                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6593                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6594                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6595                                 
6596
6597                         g_free (assembly->image.raw_metadata);
6598                         break;
6599                 case MONO_SECTION_RELOC: {
6600                         struct {
6601                                 guint32 page_rva;
6602                                 guint32 block_size;
6603                                 guint16 type_and_offset;
6604                                 guint16 term;
6605                         } reloc;
6606                         
6607                         g_assert (sizeof (reloc) == 12);
6608                         
6609                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6610                         reloc.block_size = GUINT32_FROM_LE (12);
6611                         
6612                         /* 
6613                          * the entrypoint is always at the start of the text section 
6614                          * 3 is IMAGE_REL_BASED_HIGHLOW
6615                          * 2 is patch_size_rva - text_rva
6616                          */
6617                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6618                         reloc.term = 0;
6619                         
6620                         checked_write_file (file, &reloc, sizeof (reloc));
6621                         
6622                         break;
6623                 }
6624                 case MONO_SECTION_RSRC:
6625                         if (assembly->win32_res) {
6626
6627                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6628                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6629                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6630                         }
6631                         break;
6632                 default:
6633                         g_assert_not_reached ();
6634                 }
6635         }
6636         
6637         /* check that the file is properly padded */
6638         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6639                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6640         if (! SetEndOfFile (file))
6641                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6642         
6643         mono_dynamic_stream_reset (&assembly->code);
6644         mono_dynamic_stream_reset (&assembly->us);
6645         mono_dynamic_stream_reset (&assembly->blob);
6646         mono_dynamic_stream_reset (&assembly->guid);
6647         mono_dynamic_stream_reset (&assembly->sheap);
6648
6649         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6650         g_hash_table_destroy (assembly->blob_cache);
6651         assembly->blob_cache = NULL;
6652
6653         return TRUE;
6654 }
6655
6656 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6657
6658 gboolean
6659 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6660 {
6661         g_assert_not_reached ();
6662 }
6663
6664 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6665
6666 #ifndef DISABLE_REFLECTION_EMIT
6667
6668 MonoReflectionModule *
6669 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6670 {
6671         MonoError error;
6672         MonoReflectionModule *result = NULL;
6673         char *name;
6674         MonoImage *image;
6675         MonoImageOpenStatus status;
6676         MonoDynamicAssembly *assembly;
6677         guint32 module_count;
6678         MonoImage **new_modules;
6679         gboolean *new_modules_loaded;
6680         
6681         name = mono_string_to_utf8 (fileName);
6682
6683         image = mono_image_open (name, &status);
6684         if (!image) {
6685                 MonoException *exc;
6686                 if (status == MONO_IMAGE_ERROR_ERRNO)
6687                         exc = mono_get_exception_file_not_found (fileName);
6688                 else
6689                         exc = mono_get_exception_bad_image_format (name);
6690                 g_free (name);
6691                 mono_raise_exception (exc);
6692         }
6693
6694         g_free (name);
6695
6696         assembly = ab->dynamic_assembly;
6697         image->assembly = (MonoAssembly*)assembly;
6698
6699         module_count = image->assembly->image->module_count;
6700         new_modules = g_new0 (MonoImage *, module_count + 1);
6701         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6702
6703         if (image->assembly->image->modules)
6704                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6705         if (image->assembly->image->modules_loaded)
6706                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6707         new_modules [module_count] = image;
6708         new_modules_loaded [module_count] = TRUE;
6709         mono_image_addref (image);
6710
6711         g_free (image->assembly->image->modules);
6712         image->assembly->image->modules = new_modules;
6713         image->assembly->image->modules_loaded = new_modules_loaded;
6714         image->assembly->image->module_count ++;
6715
6716         mono_assembly_load_references (image, &status);
6717         if (status) {
6718                 mono_image_close (image);
6719                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6720         }
6721
6722         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6723         mono_error_raise_exception (&error); /* FIXME don't raise here */
6724         return result;
6725 }
6726
6727 #endif /* DISABLE_REFLECTION_EMIT */
6728
6729 /*
6730  * We need to return always the same object for MethodInfo, FieldInfo etc..
6731  * but we need to consider the reflected type.
6732  * type uses a different hash, since it uses custom hash/equal functions.
6733  */
6734
6735 typedef struct {
6736         gpointer item;
6737         MonoClass *refclass;
6738 } ReflectedEntry;
6739
6740 static gboolean
6741 reflected_equal (gconstpointer a, gconstpointer b) {
6742         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6743         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6744
6745         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6746 }
6747
6748 static guint
6749 reflected_hash (gconstpointer a) {
6750         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6751         return mono_aligned_addr_hash (ea->item);
6752 }
6753
6754 #define CHECK_OBJECT(t,p,k)     \
6755         do {    \
6756                 t _obj; \
6757                 ReflectedEntry e;       \
6758                 e.item = (p);   \
6759                 e.refclass = (k);       \
6760                 mono_domain_lock (domain);      \
6761                 if (!domain->refobject_hash)    \
6762                         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");  \
6763                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6764                         mono_domain_unlock (domain);    \
6765                         return _obj;    \
6766                 }       \
6767         mono_domain_unlock (domain); \
6768         } while (0)
6769
6770 #ifdef HAVE_BOEHM_GC
6771 /* ReflectedEntry doesn't need to be GC tracked */
6772 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6773 #define FREE_REFENTRY(entry) g_free ((entry))
6774 #define REFENTRY_REQUIRES_CLEANUP
6775 #else
6776 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6777 /* FIXME: */
6778 #define FREE_REFENTRY(entry)
6779 #endif
6780
6781 #define CACHE_OBJECT(t,p,o,k)   \
6782         do {    \
6783                 t _obj; \
6784         ReflectedEntry pe; \
6785         pe.item = (p); \
6786         pe.refclass = (k); \
6787         mono_domain_lock (domain); \
6788                 if (!domain->refobject_hash)    \
6789                         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");  \
6790         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6791         if (!_obj) { \
6792                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6793                     e->item = (p);      \
6794                     e->refclass = (k);  \
6795                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6796             _obj = o; \
6797         } \
6798                 mono_domain_unlock (domain);    \
6799         return _obj; \
6800         } while (0)
6801
6802 static void
6803 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6804 {
6805         mono_domain_lock (domain);
6806         if (domain->refobject_hash) {
6807         ReflectedEntry pe;
6808                 gpointer orig_pe, orig_value;
6809
6810                 pe.item = o;
6811                 pe.refclass = klass;
6812                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6813                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6814                         FREE_REFENTRY (orig_pe);
6815                 }
6816         }
6817         mono_domain_unlock (domain);
6818 }
6819
6820 #ifdef REFENTRY_REQUIRES_CLEANUP
6821 static void
6822 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6823 {
6824         FREE_REFENTRY (key);
6825 }
6826 #endif
6827
6828 void
6829 mono_reflection_cleanup_domain (MonoDomain *domain)
6830 {
6831         if (domain->refobject_hash) {
6832 /*let's avoid scanning the whole hashtable if not needed*/
6833 #ifdef REFENTRY_REQUIRES_CLEANUP
6834                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6835 #endif
6836                 mono_g_hash_table_destroy (domain->refobject_hash);
6837                 domain->refobject_hash = NULL;
6838         }
6839 }
6840
6841 #ifndef DISABLE_REFLECTION_EMIT
6842 static gpointer
6843 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6844 {
6845         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6846 }
6847
6848 static gpointer
6849 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6850 {
6851         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6852 }
6853
6854 void
6855 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6856 {
6857         MonoDynamicImage *image = moduleb->dynamic_image;
6858         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6859         if (!image) {
6860                 MonoError error;
6861                 int module_count;
6862                 MonoImage **new_modules;
6863                 MonoImage *ass;
6864                 char *name, *fqname;
6865                 /*
6866                  * FIXME: we already created an image in mono_image_basic_init (), but
6867                  * we don't know which module it belongs to, since that is only 
6868                  * determined at assembly save time.
6869                  */
6870                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6871                 name = mono_string_to_utf8 (ab->name);
6872                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6873                 if (!mono_error_ok (&error)) {
6874                         g_free (name);
6875                         mono_error_raise_exception (&error);
6876                 }
6877                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6878
6879                 moduleb->module.image = &image->image;
6880                 moduleb->dynamic_image = image;
6881                 register_module (mono_object_domain (moduleb), moduleb, image);
6882
6883                 /* register the module with the assembly */
6884                 ass = ab->dynamic_assembly->assembly.image;
6885                 module_count = ass->module_count;
6886                 new_modules = g_new0 (MonoImage *, module_count + 1);
6887
6888                 if (ass->modules)
6889                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6890                 new_modules [module_count] = &image->image;
6891                 mono_image_addref (&image->image);
6892
6893                 g_free (ass->modules);
6894                 ass->modules = new_modules;
6895                 ass->module_count ++;
6896         }
6897 }
6898
6899 void
6900 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6901 {
6902         MonoDynamicImage *image = moduleb->dynamic_image;
6903
6904         g_assert (type->type);
6905         image->wrappers_type = mono_class_from_mono_type (type->type);
6906 }
6907
6908 #endif
6909
6910 /*
6911  * mono_assembly_get_object:
6912  * @domain: an app domain
6913  * @assembly: an assembly
6914  *
6915  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6916  */
6917 MonoReflectionAssembly*
6918 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6919 {
6920         MonoError error;
6921         MonoReflectionAssembly *result;
6922         result = mono_assembly_get_object_checked (domain, assembly, &error);
6923         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6924         return result;
6925 }
6926 /*
6927  * mono_assembly_get_object_checked:
6928  * @domain: an app domain
6929  * @assembly: an assembly
6930  *
6931  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6932  */
6933 MonoReflectionAssembly*
6934 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6935 {
6936         MonoReflectionAssembly *res;
6937         
6938         mono_error_init (error);
6939
6940         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6941         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6942         if (!res)
6943                 return NULL;
6944         res->assembly = assembly;
6945
6946         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6947 }
6948
6949
6950
6951 MonoReflectionModule*   
6952 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6953 {
6954         MonoError error;
6955         MonoReflectionModule *result;
6956         result = mono_module_get_object_checked (domain, image, &error);
6957         mono_error_raise_exception (&error);
6958         return result;
6959 }
6960
6961 MonoReflectionModule*
6962 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6963 {
6964         MonoReflectionModule *res;
6965         char* basename;
6966         
6967         mono_error_init (error);
6968         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6969         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6970         if (!res)
6971                 return NULL;
6972
6973         res->image = image;
6974         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6975         if (!assm_obj)
6976                 return NULL;
6977         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6978
6979         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6980         basename = g_path_get_basename (image->name);
6981         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6982         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6983         
6984         g_free (basename);
6985
6986         if (image->assembly->image == image) {
6987                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6988         } else {
6989                 int i;
6990                 res->token = 0;
6991                 if (image->assembly->image->modules) {
6992                         for (i = 0; i < image->assembly->image->module_count; i++) {
6993                                 if (image->assembly->image->modules [i] == image)
6994                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6995                         }
6996                         g_assert (res->token);
6997                 }
6998         }
6999
7000         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
7001 }
7002
7003 MonoReflectionModule*
7004 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
7005 {
7006         MonoError error;
7007         MonoReflectionModule *result;
7008         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
7009         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
7010         return result;
7011 }
7012
7013 MonoReflectionModule*
7014 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
7015 {
7016         MonoReflectionModule *res;
7017         MonoTableInfo *table;
7018         guint32 cols [MONO_FILE_SIZE];
7019         const char *name;
7020         guint32 i, name_idx;
7021         const char *val;
7022         
7023         mono_error_init (error);
7024
7025         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7026         if (!res)
7027                 return NULL;
7028
7029         table = &image->tables [MONO_TABLE_FILE];
7030         g_assert (table_index < table->rows);
7031         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7032
7033         res->image = NULL;
7034         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7035         if (!assm_obj)
7036                 return NULL;
7037         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7038         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7039
7040         /* Check whenever the row has a corresponding row in the moduleref table */
7041         table = &image->tables [MONO_TABLE_MODULEREF];
7042         for (i = 0; i < table->rows; ++i) {
7043                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7044                 val = mono_metadata_string_heap (image, name_idx);
7045                 if (strcmp (val, name) == 0)
7046                         res->image = image->modules [i];
7047         }
7048
7049         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7050         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7051         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7052         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7053         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7054
7055         return res;
7056 }
7057
7058 static gboolean
7059 verify_safe_for_managed_space (MonoType *type)
7060 {
7061         switch (type->type) {
7062 #ifdef DEBUG_HARDER
7063         case MONO_TYPE_ARRAY:
7064                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7065         case MONO_TYPE_PTR:
7066                 return verify_safe_for_managed_space (type->data.type);
7067         case MONO_TYPE_SZARRAY:
7068                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7069         case MONO_TYPE_GENERICINST: {
7070                 MonoGenericInst *inst = type->data.generic_class->inst;
7071                 int i;
7072                 if (!inst->is_open)
7073                         break;
7074                 for (i = 0; i < inst->type_argc; ++i)
7075                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7076                                 return FALSE;
7077                 return TRUE;
7078         }
7079 #endif
7080         case MONO_TYPE_VAR:
7081         case MONO_TYPE_MVAR:
7082                 return TRUE;
7083         default:
7084                 return TRUE;
7085         }
7086 }
7087
7088 static MonoType*
7089 mono_type_normalize (MonoType *type)
7090 {
7091         int i;
7092         MonoGenericClass *gclass;
7093         MonoGenericInst *ginst;
7094         MonoClass *gtd;
7095         MonoGenericContainer *gcontainer;
7096         MonoType **argv = NULL;
7097         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7098
7099         if (type->type != MONO_TYPE_GENERICINST)
7100                 return type;
7101
7102         gclass = type->data.generic_class;
7103         ginst = gclass->context.class_inst;
7104         if (!ginst->is_open)
7105                 return type;
7106
7107         gtd = gclass->container_class;
7108         gcontainer = gtd->generic_container;
7109         argv = g_newa (MonoType*, ginst->type_argc);
7110
7111         for (i = 0; i < ginst->type_argc; ++i) {
7112                 MonoType *t = ginst->type_argv [i], *norm;
7113                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7114                         is_denorm_gtd = FALSE;
7115                 norm = mono_type_normalize (t);
7116                 argv [i] = norm;
7117                 if (norm != t)
7118                         requires_rebind = TRUE;
7119         }
7120
7121         if (is_denorm_gtd)
7122                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7123
7124         if (requires_rebind) {
7125                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7126                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7127         }
7128
7129         return type;
7130 }
7131 /*
7132  * mono_type_get_object:
7133  * @domain: an app domain
7134  * @type: a type
7135  *
7136  * Return an System.MonoType object representing the type @type.
7137  */
7138 MonoReflectionType*
7139 mono_type_get_object (MonoDomain *domain, MonoType *type)
7140 {
7141         MonoError error;
7142         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7143         mono_error_raise_exception (&error);
7144
7145         return ret;
7146 }
7147
7148 MonoReflectionType*
7149 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7150 {
7151         MonoType *norm_type;
7152         MonoReflectionType *res;
7153         MonoClass *klass;
7154
7155         mono_error_init (error);
7156
7157         klass = mono_class_from_mono_type (type);
7158
7159         /*we must avoid using @type as it might have come
7160          * from a mono_metadata_type_dup and the caller
7161          * expects that is can be freed.
7162          * Using the right type from 
7163          */
7164         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7165
7166         /* void is very common */
7167         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7168                 return (MonoReflectionType*)domain->typeof_void;
7169
7170         /*
7171          * If the vtable of the given class was already created, we can use
7172          * the MonoType from there and avoid all locking and hash table lookups.
7173          * 
7174          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7175          * that the resulting object is different.   
7176          */
7177         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7178                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7179                 if (vtable && vtable->type)
7180                         return (MonoReflectionType *)vtable->type;
7181         }
7182
7183         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7184         mono_domain_lock (domain);
7185         if (!domain->type_hash)
7186                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7187                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7188         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7189                 mono_domain_unlock (domain);
7190                 mono_loader_unlock ();
7191                 return res;
7192         }
7193
7194         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7195          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7196          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7197          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7198          * artifact of how generics are encoded and should be transparent to managed code so we
7199          * need to weed out this diference when retrieving managed System.Type objects.
7200          */
7201         norm_type = mono_type_normalize (type);
7202         if (norm_type != type) {
7203                 res = mono_type_get_object_checked (domain, norm_type, error);
7204                 if (!mono_error_ok (error))
7205                         return NULL;
7206                 mono_g_hash_table_insert (domain->type_hash, type, res);
7207                 mono_domain_unlock (domain);
7208                 mono_loader_unlock ();
7209                 return res;
7210         }
7211
7212         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7213         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7214                 g_assert (0);
7215
7216         if (!verify_safe_for_managed_space (type)) {
7217                 mono_domain_unlock (domain);
7218                 mono_loader_unlock ();
7219                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7220                 return NULL;
7221         }
7222
7223         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7224                 gboolean is_type_done = TRUE;
7225                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7226                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7227                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7228                 */
7229                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7230                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7231
7232                         if (gparam->owner && gparam->owner->is_method) {
7233                                 MonoMethod *method = gparam->owner->owner.method;
7234                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7235                                         is_type_done = FALSE;
7236                         } else if (gparam->owner && !gparam->owner->is_method) {
7237                                 MonoClass *klass = gparam->owner->owner.klass;
7238                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7239                                         is_type_done = FALSE;
7240                         }
7241                 } 
7242
7243                 /* g_assert_not_reached (); */
7244                 /* should this be considered an error condition? */
7245                 if (is_type_done && !type->byref) {
7246                         mono_domain_unlock (domain);
7247                         mono_loader_unlock ();
7248                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7249                 }
7250         }
7251         /* This is stored in vtables/JITted code so it has to be pinned */
7252         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7253         if (!mono_error_ok (error))
7254                 return NULL;
7255
7256         res->type = type;
7257         mono_g_hash_table_insert (domain->type_hash, type, res);
7258
7259         if (type->type == MONO_TYPE_VOID)
7260                 domain->typeof_void = (MonoObject*)res;
7261
7262         mono_domain_unlock (domain);
7263         mono_loader_unlock ();
7264         return res;
7265 }
7266
7267 /*
7268  * mono_method_get_object:
7269  * @domain: an app domain
7270  * @method: a method
7271  * @refclass: the reflected type (can be NULL)
7272  *
7273  * Return an System.Reflection.MonoMethod object representing the method @method.
7274  */
7275 MonoReflectionMethod*
7276 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7277 {
7278         MonoError error;
7279         MonoReflectionMethod *ret = NULL;
7280         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7281         mono_error_raise_exception (&error);
7282         return ret;
7283 }
7284
7285 /*
7286  * mono_method_get_object_checked:
7287  * @domain: an app domain
7288  * @method: a method
7289  * @refclass: the reflected type (can be NULL)
7290  * @error: set on error.
7291  *
7292  * Return an System.Reflection.MonoMethod object representing the method @method.
7293  * Returns NULL and sets @error on error.
7294  */
7295 MonoReflectionMethod*
7296 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7297 {
7298         /*
7299          * We use the same C representation for methods and constructors, but the type 
7300          * name in C# is different.
7301          */
7302         MonoReflectionType *rt;
7303         MonoClass *klass;
7304         MonoReflectionMethod *ret;
7305
7306         mono_error_init (error);
7307
7308         if (method->is_inflated) {
7309                 MonoReflectionGenericMethod *gret;
7310
7311                 if (!refclass)
7312                         refclass = method->klass;
7313                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7314                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7315                         klass = mono_class_get_mono_generic_cmethod_class ();
7316                 } else {
7317                         klass = mono_class_get_mono_generic_method_class ();
7318                 }
7319                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7320                 if (!mono_error_ok (error))
7321                         goto leave;
7322                 gret->method.method = method;
7323
7324                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7325
7326                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7327                 if (!mono_error_ok (error))
7328                     goto leave;
7329
7330                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7331
7332                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7333         }
7334
7335         if (!refclass)
7336                 refclass = method->klass;
7337
7338         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7339         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7340                 klass = mono_class_get_mono_cmethod_class ();
7341         }
7342         else {
7343                 klass = mono_class_get_mono_method_class ();
7344         }
7345         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7346         if (!mono_error_ok (error))
7347                 goto leave;
7348         ret->method = method;
7349
7350         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7351         if (!mono_error_ok (error))
7352                 goto leave;
7353
7354         MONO_OBJECT_SETREF (ret, reftype, rt);
7355
7356         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7357
7358 leave:
7359         g_assert (!mono_error_ok (error));
7360         return NULL;
7361 }
7362
7363 /*
7364  * mono_method_clear_object:
7365  *
7366  *   Clear the cached reflection objects for the dynamic method METHOD.
7367  */
7368 void
7369 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7370 {
7371         MonoClass *klass;
7372         g_assert (method_is_dynamic (method));
7373
7374         klass = method->klass;
7375         while (klass) {
7376                 clear_cached_object (domain, method, klass);
7377                 klass = klass->parent;
7378         }
7379         /* Added by mono_param_get_objects () */
7380         clear_cached_object (domain, &(method->signature), NULL);
7381         klass = method->klass;
7382         while (klass) {
7383                 clear_cached_object (domain, &(method->signature), klass);
7384                 klass = klass->parent;
7385         }
7386 }
7387
7388 /*
7389  * mono_field_get_object:
7390  * @domain: an app domain
7391  * @klass: a type
7392  * @field: a field
7393  *
7394  * Return an System.Reflection.MonoField object representing the field @field
7395  * in class @klass.
7396  */
7397 MonoReflectionField*
7398 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7399 {
7400         MonoError error;
7401         MonoReflectionField *result;
7402         result = mono_field_get_object_checked (domain, klass, field, &error);
7403         mono_error_raise_exception (&error);
7404         return result;
7405 }
7406
7407 /*
7408  * mono_field_get_object_checked:
7409  * @domain: an app domain
7410  * @klass: a type
7411  * @field: a field
7412  * @error: set on error
7413  *
7414  * Return an System.Reflection.MonoField object representing the field @field
7415  * in class @klass. On error, returns NULL and sets @error.
7416  */
7417 MonoReflectionField*
7418 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7419 {
7420         MonoReflectionType *rt;
7421         MonoReflectionField *res;
7422
7423         mono_error_init (error);
7424
7425         CHECK_OBJECT (MonoReflectionField *, field, klass);
7426         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7427         if (!res)
7428                 return NULL;
7429         res->klass = klass;
7430         res->field = field;
7431         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7432
7433         if (is_field_on_inst (field)) {
7434                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7435
7436                 rt = mono_type_get_object_checked (domain, field->type, error);
7437                 if (!mono_error_ok (error))
7438                         return NULL;
7439
7440                 MONO_OBJECT_SETREF (res, type, rt);
7441         } else {
7442                 if (field->type) {
7443                         rt = mono_type_get_object_checked (domain, field->type, error);
7444                         if (!mono_error_ok (error))
7445                                 return NULL;
7446
7447                         MONO_OBJECT_SETREF (res, type, rt);
7448                 }
7449                 res->attrs = mono_field_get_flags (field);
7450         }
7451         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7452 }
7453
7454 /*
7455  * mono_property_get_object:
7456  * @domain: an app domain
7457  * @klass: a type
7458  * @property: a property
7459  *
7460  * Return an System.Reflection.MonoProperty object representing the property @property
7461  * in class @klass.
7462  */
7463 MonoReflectionProperty*
7464 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7465 {
7466         MonoError error;
7467         MonoReflectionProperty *result;
7468         result = mono_property_get_object_checked (domain, klass, property, &error);
7469         mono_error_raise_exception (&error);
7470         return result;
7471 }
7472
7473 /**
7474  * mono_property_get_object:
7475  * @domain: an app domain
7476  * @klass: a type
7477  * @property: a property
7478  * @error: set on error
7479  *
7480  * Return an System.Reflection.MonoProperty object representing the property @property
7481  * in class @klass.  On error returns NULL and sets @error.
7482  */
7483 MonoReflectionProperty*
7484 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7485 {
7486         MonoReflectionProperty *res;
7487
7488         mono_error_init (error);
7489
7490         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7491         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7492         if (!res)
7493                 return NULL;
7494         res->klass = klass;
7495         res->property = property;
7496         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7497 }
7498
7499 /*
7500  * mono_event_get_object:
7501  * @domain: an app domain
7502  * @klass: a type
7503  * @event: a event
7504  *
7505  * Return an System.Reflection.MonoEvent object representing the event @event
7506  * in class @klass.
7507  */
7508 MonoReflectionEvent*
7509 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7510 {
7511         MonoError error;
7512         MonoReflectionEvent *result;
7513         result = mono_event_get_object_checked (domain, klass, event, &error);
7514         mono_error_raise_exception (&error);
7515         return result;
7516 }
7517
7518 /**
7519  * mono_event_get_object_checked:
7520  * @domain: an app domain
7521  * @klass: a type
7522  * @event: a event
7523  * @error: set on error
7524  *
7525  * Return an System.Reflection.MonoEvent object representing the event @event
7526  * in class @klass. On failure sets @error and returns NULL
7527  */
7528 MonoReflectionEvent*
7529 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7530 {
7531         MonoReflectionEvent *res;
7532         MonoReflectionMonoEvent *mono_event;
7533
7534         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7535         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7536         if (!mono_event)
7537                 return NULL;
7538         mono_event->klass = klass;
7539         mono_event->event = event;
7540         res = (MonoReflectionEvent*)mono_event;
7541         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7542 }
7543
7544 /**
7545  * mono_get_reflection_missing_object:
7546  * @domain: Domain where the object lives
7547  *
7548  * Returns the System.Reflection.Missing.Value singleton object
7549  * (of type System.Reflection.Missing).
7550  *
7551  * Used as the value for ParameterInfo.DefaultValue when Optional
7552  * is present
7553  */
7554 static MonoObject *
7555 mono_get_reflection_missing_object (MonoDomain *domain)
7556 {
7557         MonoObject *obj;
7558         static MonoClassField *missing_value_field = NULL;
7559         
7560         if (!missing_value_field) {
7561                 MonoClass *missing_klass;
7562                 missing_klass = mono_class_get_missing_class ();
7563                 mono_class_init (missing_klass);
7564                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7565                 g_assert (missing_value_field);
7566         }
7567         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7568         g_assert (obj);
7569         return obj;
7570 }
7571
7572 static MonoObject*
7573 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7574 {
7575         if (!*dbnull)
7576                 *dbnull = mono_get_dbnull_object (domain);
7577         return *dbnull;
7578 }
7579
7580 static MonoObject*
7581 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7582 {
7583         if (!*reflection_missing)
7584                 *reflection_missing = mono_get_reflection_missing_object (domain);
7585         return *reflection_missing;
7586 }
7587
7588 /*
7589  * mono_param_get_objects:
7590  * @domain: an app domain
7591  * @method: a method
7592  *
7593  * Return an System.Reflection.ParameterInfo array object representing the parameters
7594  * in the method @method.
7595  */
7596 MonoArray*
7597 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7598 {
7599         static MonoClass *System_Reflection_ParameterInfo;
7600         static MonoClass *System_Reflection_ParameterInfo_array;
7601         MonoError error;
7602         MonoArray *res = NULL;
7603         MonoReflectionMethod *member = NULL;
7604         MonoReflectionParameter *param = NULL;
7605         char **names = NULL, **blobs = NULL;
7606         guint32 *types = NULL;
7607         MonoType *type = NULL;
7608         MonoObject *dbnull = NULL;
7609         MonoObject *missing = NULL;
7610         MonoMarshalSpec **mspecs = NULL;
7611         MonoMethodSignature *sig = NULL;
7612         MonoVTable *pinfo_vtable;
7613         MonoReflectionType *rt;
7614         int i;
7615
7616         mono_error_init (&error);
7617         
7618         if (!System_Reflection_ParameterInfo_array) {
7619                 MonoClass *klass;
7620
7621                 klass = mono_class_get_mono_parameter_info_class ();
7622
7623                 mono_memory_barrier ();
7624                 System_Reflection_ParameterInfo = klass; 
7625
7626         
7627                 klass = mono_array_class_get (klass, 1);
7628                 mono_memory_barrier ();
7629                 System_Reflection_ParameterInfo_array = klass;
7630         }
7631
7632         sig = mono_method_signature_checked (method, &error);
7633         if (!mono_error_ok (&error))
7634                 goto leave;
7635
7636         if (!sig->param_count) {
7637                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7638                 if (!res)
7639                         goto leave;
7640
7641                 return res;
7642         }
7643
7644         /* Note: the cache is based on the address of the signature into the method
7645          * since we already cache MethodInfos with the method as keys.
7646          */
7647         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7648
7649         member = mono_method_get_object_checked (domain, method, refclass, &error);
7650         if (!member)
7651                 goto leave;
7652         names = g_new (char *, sig->param_count);
7653         mono_method_get_param_names (method, (const char **) names);
7654
7655         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7656         mono_method_get_marshal_info (method, mspecs);
7657
7658         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7659         if (!res)
7660                 goto leave;
7661
7662         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7663         for (i = 0; i < sig->param_count; ++i) {
7664                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7665                 if (!param)
7666                         goto leave;
7667
7668                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7669                 if (!rt)
7670                         goto leave;
7671
7672                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7673
7674                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7675
7676                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7677
7678                 param->PositionImpl = i;
7679                 param->AttrsImpl = sig->params [i]->attrs;
7680
7681                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7682                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7683                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7684                         else
7685                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7686                 } else {
7687
7688                         if (!blobs) {
7689                                 blobs = g_new0 (char *, sig->param_count);
7690                                 types = g_new0 (guint32, sig->param_count);
7691                                 get_default_param_value_blobs (method, blobs, types); 
7692                         }
7693
7694                         /* Build MonoType for the type from the Constant Table */
7695                         if (!type)
7696                                 type = g_new0 (MonoType, 1);
7697                         type->type = (MonoTypeEnum)types [i];
7698                         type->data.klass = NULL;
7699                         if (types [i] == MONO_TYPE_CLASS)
7700                                 type->data.klass = mono_defaults.object_class;
7701                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7702                                 /* For enums, types [i] contains the base type */
7703
7704                                         type->type = MONO_TYPE_VALUETYPE;
7705                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7706                         } else
7707                                 type->data.klass = mono_class_from_mono_type (type);
7708
7709                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7710
7711                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7712                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7713                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7714                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7715                                 else
7716                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7717                         }
7718                         
7719                 }
7720
7721                 if (mspecs [i + 1]) {
7722                         MonoReflectionMarshalAsAttribute* mobj;
7723                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7724                         if (!mobj)
7725                                 goto leave;
7726                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7727                 }
7728                 
7729                 mono_array_setref (res, i, param);
7730         }
7731
7732 leave:
7733         g_free (names);
7734         g_free (blobs);
7735         g_free (types);
7736         g_free (type);
7737
7738         if (sig) {
7739                 for (i = sig->param_count; i >= 0; i--) {
7740                         if (mspecs [i])
7741                                 mono_metadata_free_marshal_spec (mspecs [i]);
7742                 }
7743         }
7744         g_free (mspecs);
7745
7746         mono_error_raise_exception (&error); /* FIXME don't raise here */
7747         
7748         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7749 }
7750
7751 MonoArray*
7752 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7753 {
7754         return mono_param_get_objects_internal (domain, method, NULL);
7755 }
7756
7757 /*
7758  * mono_method_body_get_object:
7759  * @domain: an app domain
7760  * @method: a method
7761  *
7762  * Return an System.Reflection.MethodBody object representing the method @method.
7763  */
7764 MonoReflectionMethodBody*
7765 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7766 {
7767         MonoError error;
7768         MonoReflectionMethodBody *ret;
7769         MonoMethodHeader *header;
7770         MonoImage *image;
7771         MonoReflectionType *rt;
7772         guint32 method_rva, local_var_sig_token;
7773     char *ptr;
7774         unsigned char format, flags;
7775         int i;
7776
7777         /* for compatibility with .net */
7778     if (method_is_dynamic (method))
7779         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7780
7781         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7782
7783         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7784                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7785             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7786                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7787             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7788                 return NULL;
7789
7790         image = method->klass->image;
7791         header = mono_method_get_header_checked (method, &error);
7792         mono_error_raise_exception (&error); /* FIXME don't raise here */
7793
7794         if (!image_is_dynamic (image)) {
7795                 /* Obtain local vars signature token */
7796                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7797                 ptr = mono_image_rva_map (image, method_rva);
7798                 flags = *(const unsigned char *) ptr;
7799                 format = flags & METHOD_HEADER_FORMAT_MASK;
7800                 switch (format){
7801                 case METHOD_HEADER_TINY_FORMAT:
7802                         local_var_sig_token = 0;
7803                         break;
7804                 case METHOD_HEADER_FAT_FORMAT:
7805                         ptr += 2;
7806                         ptr += 2;
7807                         ptr += 4;
7808                         local_var_sig_token = read32 (ptr);
7809                         break;
7810                 default:
7811                         g_assert_not_reached ();
7812                 }
7813         } else
7814                 local_var_sig_token = 0; //FIXME
7815
7816         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7817         mono_error_raise_exception (&error); /* FIXME don't raise here */
7818
7819         ret->init_locals = header->init_locals;
7820         ret->max_stack = header->max_stack;
7821         ret->local_var_sig_token = local_var_sig_token;
7822         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7823         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7824
7825         /* Locals */
7826         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7827         for (i = 0; i < header->num_locals; ++i) {
7828                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7829                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7830
7831                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7832                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7833
7834                 MONO_OBJECT_SETREF (info, local_type, rt);
7835
7836                 info->is_pinned = header->locals [i]->pinned;
7837                 info->local_index = i;
7838                 mono_array_setref (ret->locals, i, info);
7839         }
7840
7841         /* Exceptions */
7842         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7843         for (i = 0; i < header->num_clauses; ++i) {
7844                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7845                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7846                 MonoExceptionClause *clause = &header->clauses [i];
7847
7848                 info->flags = clause->flags;
7849                 info->try_offset = clause->try_offset;
7850                 info->try_length = clause->try_len;
7851                 info->handler_offset = clause->handler_offset;
7852                 info->handler_length = clause->handler_len;
7853                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7854                         info->filter_offset = clause->data.filter_offset;
7855                 else if (clause->data.catch_class) {
7856                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7857                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7858
7859                         MONO_OBJECT_SETREF (info, catch_type, rt);
7860                 }
7861
7862                 mono_array_setref (ret->clauses, i, info);
7863         }
7864
7865         mono_metadata_free_mh (header);
7866         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7867         return ret;
7868 }
7869
7870 /**
7871  * mono_get_dbnull_object:
7872  * @domain: Domain where the object lives
7873  *
7874  * Returns the System.DBNull.Value singleton object
7875  *
7876  * Used as the value for ParameterInfo.DefaultValue 
7877  */
7878 MonoObject *
7879 mono_get_dbnull_object (MonoDomain *domain)
7880 {
7881         MonoObject *obj;
7882         static MonoClassField *dbnull_value_field = NULL;
7883         
7884         if (!dbnull_value_field) {
7885                 MonoClass *dbnull_klass;
7886                 dbnull_klass = mono_class_get_dbnull_class ();
7887                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7888                 g_assert (dbnull_value_field);
7889         }
7890         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7891         g_assert (obj);
7892         return obj;
7893 }
7894
7895 static void
7896 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7897 {
7898         guint32 param_index, i, lastp, crow = 0;
7899         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7900         gint32 idx;
7901
7902         MonoClass *klass = method->klass;
7903         MonoImage *image = klass->image;
7904         MonoMethodSignature *methodsig = mono_method_signature (method);
7905
7906         MonoTableInfo *constt;
7907         MonoTableInfo *methodt;
7908         MonoTableInfo *paramt;
7909
7910         if (!methodsig->param_count)
7911                 return;
7912
7913         mono_class_init (klass);
7914
7915         if (image_is_dynamic (klass->image)) {
7916                 MonoReflectionMethodAux *aux;
7917                 if (method->is_inflated)
7918                         method = ((MonoMethodInflated*)method)->declaring;
7919                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7920                 if (aux && aux->param_defaults) {
7921                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7922                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7923                 }
7924                 return;
7925         }
7926
7927         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7928         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7929         constt = &image->tables [MONO_TABLE_CONSTANT];
7930
7931         idx = mono_method_get_index (method) - 1;
7932         g_assert (idx != -1);
7933
7934         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7935         if (idx + 1 < methodt->rows)
7936                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7937         else
7938                 lastp = paramt->rows + 1;
7939
7940         for (i = param_index; i < lastp; ++i) {
7941                 guint32 paramseq;
7942
7943                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7944                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7945
7946                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7947                         continue;
7948
7949                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7950                 if (!crow) {
7951                         continue;
7952                 }
7953         
7954                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7955                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7956                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7957         }
7958
7959         return;
7960 }
7961
7962 MonoObject *
7963 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7964 {
7965         MonoError error;
7966         void *retval;
7967         MonoClass *klass;
7968         MonoObject *object;
7969         MonoType *basetype = type;
7970
7971         if (!blob)
7972                 return NULL;
7973         
7974         klass = mono_class_from_mono_type (type);
7975         if (klass->valuetype) {
7976                 object = mono_object_new_checked (domain, klass, &error);
7977                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7978                 retval = ((gchar *) object + sizeof (MonoObject));
7979                 if (klass->enumtype)
7980                         basetype = mono_class_enum_basetype (klass);
7981         } else {
7982                 retval = &object;
7983         }
7984                         
7985         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7986                 return object;
7987         else
7988                 return NULL;
7989 }
7990
7991 static int
7992 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7993         int found_sep;
7994         char *s;
7995         gboolean quoted = FALSE;
7996
7997         memset (assembly, 0, sizeof (MonoAssemblyName));
7998         assembly->culture = "";
7999         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
8000
8001         if (*p == '"') {
8002                 quoted = TRUE;
8003                 p++;
8004         }
8005         assembly->name = p;
8006         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
8007                 p++;
8008         if (quoted) {
8009                 if (*p != '"')
8010                         return 1;
8011                 *p = 0;
8012                 p++;
8013         }
8014         if (*p != ',')
8015                 return 1;
8016         *p = 0;
8017         /* Remove trailing whitespace */
8018         s = p - 1;
8019         while (*s && g_ascii_isspace (*s))
8020                 *s-- = 0;
8021         p ++;
8022         while (g_ascii_isspace (*p))
8023                 p++;
8024         while (*p) {
8025                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8026                         p += 8;
8027                         assembly->major = strtoul (p, &s, 10);
8028                         if (s == p || *s != '.')
8029                                 return 1;
8030                         p = ++s;
8031                         assembly->minor = strtoul (p, &s, 10);
8032                         if (s == p || *s != '.')
8033                                 return 1;
8034                         p = ++s;
8035                         assembly->build = strtoul (p, &s, 10);
8036                         if (s == p || *s != '.')
8037                                 return 1;
8038                         p = ++s;
8039                         assembly->revision = strtoul (p, &s, 10);
8040                         if (s == p)
8041                                 return 1;
8042                         p = s;
8043                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8044                         p += 8;
8045                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8046                                 assembly->culture = "";
8047                                 p += 7;
8048                         } else {
8049                                 assembly->culture = p;
8050                                 while (*p && *p != ',') {
8051                                         p++;
8052                                 }
8053                         }
8054                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8055                         p += 15;
8056                         if (strncmp (p, "null", 4) == 0) {
8057                                 p += 4;
8058                         } else {
8059                                 int len;
8060                                 gchar *start = p;
8061                                 while (*p && *p != ',') {
8062                                         p++;
8063                                 }
8064                                 len = (p - start + 1);
8065                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8066                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8067                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8068                         }
8069                 } else {
8070                         while (*p && *p != ',')
8071                                 p++;
8072                 }
8073                 found_sep = 0;
8074                 while (g_ascii_isspace (*p) || *p == ',') {
8075                         *p++ = 0;
8076                         found_sep = 1;
8077                         continue;
8078                 }
8079                 /* failed */
8080                 if (!found_sep)
8081                         return 1;
8082         }
8083
8084         return 0;
8085 }
8086
8087 /*
8088  * mono_reflection_parse_type:
8089  * @name: type name
8090  *
8091  * Parse a type name as accepted by the GetType () method and output the info
8092  * extracted in the info structure.
8093  * the name param will be mangled, so, make a copy before passing it to this function.
8094  * The fields in info will be valid until the memory pointed to by name is valid.
8095  *
8096  * See also mono_type_get_name () below.
8097  *
8098  * Returns: 0 on parse error.
8099  */
8100 static int
8101 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8102                              MonoTypeNameParse *info)
8103 {
8104         char *start, *p, *w, *last_point, *startn;
8105         int in_modifiers = 0;
8106         int isbyref = 0, rank = 0, isptr = 0;
8107
8108         start = p = w = name;
8109
8110         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8111         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8112         info->name = info->name_space = NULL;
8113         info->nested = NULL;
8114         info->modifiers = NULL;
8115         info->type_arguments = NULL;
8116
8117         /* last_point separates the namespace from the name */
8118         last_point = NULL;
8119         /* Skips spaces */
8120         while (*p == ' ') p++, start++, w++, name++;
8121
8122         while (*p) {
8123                 switch (*p) {
8124                 case '+':
8125                         *p = 0; /* NULL terminate the name */
8126                         startn = p + 1;
8127                         info->nested = g_list_append (info->nested, startn);
8128                         /* we have parsed the nesting namespace + name */
8129                         if (info->name)
8130                                 break;
8131                         if (last_point) {
8132                                 info->name_space = start;
8133                                 *last_point = 0;
8134                                 info->name = last_point + 1;
8135                         } else {
8136                                 info->name_space = (char *)"";
8137                                 info->name = start;
8138                         }
8139                         break;
8140                 case '.':
8141                         last_point = p;
8142                         break;
8143                 case '\\':
8144                         ++p;
8145                         break;
8146                 case '&':
8147                 case '*':
8148                 case '[':
8149                 case ',':
8150                 case ']':
8151                         in_modifiers = 1;
8152                         break;
8153                 default:
8154                         break;
8155                 }
8156                 if (in_modifiers)
8157                         break;
8158                 // *w++ = *p++;
8159                 p++;
8160         }
8161         
8162         if (!info->name) {
8163                 if (last_point) {
8164                         info->name_space = start;
8165                         *last_point = 0;
8166                         info->name = last_point + 1;
8167                 } else {
8168                         info->name_space = (char *)"";
8169                         info->name = start;
8170                 }
8171         }
8172         while (*p) {
8173                 switch (*p) {
8174                 case '&':
8175                         if (isbyref) /* only one level allowed by the spec */
8176                                 return 0;
8177                         isbyref = 1;
8178                         isptr = 0;
8179                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8180                         *p++ = 0;
8181                         break;
8182                 case '*':
8183                         if (isbyref) /* pointer to ref not okay */
8184                                 return 0;
8185                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8186                         isptr = 1;
8187                         *p++ = 0;
8188                         break;
8189                 case '[':
8190                         if (isbyref) /* array of ref and generic ref are not okay */
8191                                 return 0;
8192                         //Decide if it's an array of a generic argument list
8193                         *p++ = 0;
8194
8195                         if (!*p) //XXX test
8196                                 return 0;
8197                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8198                                 isptr = 0;
8199                                 rank = 1;
8200                                 while (*p) {
8201                                         if (*p == ']')
8202                                                 break;
8203                                         if (*p == ',')
8204                                                 rank++;
8205                                         else if (*p == '*') /* '*' means unknown lower bound */
8206                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8207                                         else
8208                                                 return 0;
8209                                         ++p;
8210                                 }
8211                                 if (*p++ != ']')
8212                                         return 0;
8213                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8214                         } else {
8215                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8216                                         return 0;
8217                                 isptr = 0;
8218                                 info->type_arguments = g_ptr_array_new ();
8219                                 while (*p) {
8220                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8221                                         gboolean fqname = FALSE;
8222
8223                                         g_ptr_array_add (info->type_arguments, subinfo);
8224
8225                                         while (*p == ' ') p++;
8226                                         if (*p == '[') {
8227                                                 p++;
8228                                                 fqname = TRUE;
8229                                         }
8230
8231                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8232                                                 return 0;
8233
8234                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8235                                         if (fqname && (*p != ']')) {
8236                                                 char *aname;
8237
8238                                                 if (*p != ',')
8239                                                         return 0;
8240                                                 *p++ = 0;
8241
8242                                                 aname = p;
8243                                                 while (*p && (*p != ']'))
8244                                                         p++;
8245
8246                                                 if (*p != ']')
8247                                                         return 0;
8248
8249                                                 *p++ = 0;
8250                                                 while (*aname) {
8251                                                         if (g_ascii_isspace (*aname)) {
8252                                                                 ++aname;
8253                                                                 continue;
8254                                                         }
8255                                                         break;
8256                                                 }
8257                                                 if (!*aname ||
8258                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8259                                                         return 0;
8260                                         } else if (fqname && (*p == ']')) {
8261                                                 *p++ = 0;
8262                                         }
8263                                         if (*p == ']') {
8264                                                 *p++ = 0;
8265                                                 break;
8266                                         } else if (!*p) {
8267                                                 return 0;
8268                                         }
8269                                         *p++ = 0;
8270                                 }
8271                         }
8272                         break;
8273                 case ']':
8274                         if (is_recursed)
8275                                 goto end;
8276                         return 0;
8277                 case ',':
8278                         if (is_recursed)
8279                                 goto end;
8280                         *p++ = 0;
8281                         while (*p) {
8282                                 if (g_ascii_isspace (*p)) {
8283                                         ++p;
8284                                         continue;
8285                                 }
8286                                 break;
8287                         }
8288                         if (!*p)
8289                                 return 0; /* missing assembly name */
8290                         if (!assembly_name_to_aname (&info->assembly, p))
8291                                 return 0;
8292                         break;
8293                 default:
8294                         return 0;
8295                 }
8296                 if (info->assembly.name)
8297                         break;
8298         }
8299         // *w = 0; /* terminate class name */
8300  end:
8301         if (!info->name || !*info->name)
8302                 return 0;
8303         if (endptr)
8304                 *endptr = p;
8305         /* add other consistency checks */
8306         return 1;
8307 }
8308
8309
8310 /**
8311  * mono_identifier_unescape_type_name_chars:
8312  * @identifier: the display name of a mono type
8313  *
8314  * Returns:
8315  *  The name in internal form, that is without escaping backslashes.
8316  *
8317  *  The string is modified in place!
8318  */
8319 char*
8320 mono_identifier_unescape_type_name_chars(char* identifier)
8321 {
8322         char *w, *r;
8323         if (!identifier)
8324                 return NULL;
8325         for (w = r = identifier; *r != 0; r++)
8326         {
8327                 char c = *r;
8328                 if (c == '\\') {
8329                         r++;
8330                         if (*r == 0)
8331                                 break;
8332                         c = *r;
8333                 }
8334                 *w = c;
8335                 w++;
8336         }
8337         if (w != r)
8338                 *w = 0;
8339         return identifier;
8340 }
8341
8342 void
8343 mono_identifier_unescape_info (MonoTypeNameParse* info);
8344
8345 static void
8346 unescape_each_type_argument(void* data, void* user_data)
8347 {
8348         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8349         mono_identifier_unescape_info (info);
8350 }
8351
8352 static void
8353 unescape_each_nested_name (void* data, void* user_data)
8354 {
8355         char* nested_name = (char*) data;
8356         mono_identifier_unescape_type_name_chars(nested_name);
8357 }
8358
8359 /**
8360  * mono_identifier_unescape_info:
8361  *
8362  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8363  *
8364  * Returns: nothing.
8365  *
8366  * Destructively updates the info by unescaping the identifiers that
8367  * comprise the type namespace, name, nested types (if any) and
8368  * generic type arguments (if any).
8369  *
8370  * The resulting info has the names in internal form.
8371  *
8372  */
8373 void
8374 mono_identifier_unescape_info (MonoTypeNameParse *info)
8375 {
8376         if (!info)
8377                 return;
8378         mono_identifier_unescape_type_name_chars(info->name_space);
8379         mono_identifier_unescape_type_name_chars(info->name);
8380         // but don't escape info->assembly
8381         if (info->type_arguments)
8382                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8383         if (info->nested)
8384                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8385 }
8386
8387 int
8388 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8389 {
8390         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8391         if (ok) {
8392                 mono_identifier_unescape_info (info);
8393         }
8394         return ok;
8395 }
8396
8397 static MonoType*
8398 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8399 {
8400         gboolean type_resolve = FALSE;
8401         MonoType *type;
8402         MonoImage *rootimage = image;
8403
8404         if (info->assembly.name) {
8405                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8406                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8407                         /* 
8408                          * This could happen in the AOT compiler case when the search hook is not
8409                          * installed.
8410                          */
8411                         assembly = image->assembly;
8412                 if (!assembly) {
8413                         /* then we must load the assembly ourselve - see #60439 */
8414                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8415                         if (!assembly)
8416                                 return NULL;
8417                 }
8418                 image = assembly->image;
8419         } else if (!image) {
8420                 image = mono_defaults.corlib;
8421         }
8422
8423         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8424         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8425                 image = mono_defaults.corlib;
8426                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8427         }
8428
8429         return type;
8430 }
8431
8432 /**
8433  * mono_reflection_get_type_internal:
8434  *
8435  * Returns: may return NULL on success, sets error on failure.
8436  */
8437 static MonoType*
8438 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8439 {
8440         MonoClass *klass;
8441         GList *mod;
8442         int modval;
8443         gboolean bounded = FALSE;
8444         
8445         mono_error_init (error);
8446         if (!image)
8447                 image = mono_defaults.corlib;
8448
8449         if (!rootimage)
8450                 rootimage = mono_defaults.corlib;
8451
8452         if (ignorecase)
8453                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8454         else
8455                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8456
8457         if (!klass)
8458                 return NULL;
8459
8460         for (mod = info->nested; mod; mod = mod->next) {
8461                 gpointer iter = NULL;
8462                 MonoClass *parent;
8463
8464                 parent = klass;
8465                 mono_class_init (parent);
8466
8467                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8468                         char *lastp;
8469                         char *nested_name, *nested_nspace;
8470                         gboolean match = TRUE;
8471
8472                         lastp = strrchr ((const char *)mod->data, '.');
8473                         if (lastp) {
8474                                 /* Nested classes can have namespaces */
8475                                 int nspace_len;
8476
8477                                 nested_name = g_strdup (lastp + 1);
8478                                 nspace_len = lastp - (char*)mod->data;
8479                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8480                                 memcpy (nested_nspace, mod->data, nspace_len);
8481                                 nested_nspace [nspace_len] = '\0';
8482
8483                         } else {
8484                                 nested_name = (char *)mod->data;
8485                                 nested_nspace = NULL;
8486                         }
8487
8488                         if (nested_nspace) {
8489                                 if (ignorecase) {
8490                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8491                                                 match = FALSE;
8492                                 } else {
8493                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8494                                                 match = FALSE;
8495                                 }
8496                         }
8497                         if (match) {
8498                                 if (ignorecase) {
8499                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8500                                                 match = FALSE;
8501                                 } else {
8502                                         if (strcmp (klass->name, nested_name) != 0)
8503                                                 match = FALSE;
8504                                 }
8505                         }
8506                         if (lastp) {
8507                                 g_free (nested_name);
8508                                 g_free (nested_nspace);
8509                         }
8510                         if (match)
8511                                 break;
8512                 }
8513
8514                 if (!klass)
8515                         break;
8516         }
8517         if (!klass)
8518                 return NULL;
8519
8520         if (info->type_arguments) {
8521                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8522                 MonoReflectionType *the_type;
8523                 MonoType *instance;
8524                 int i;
8525
8526                 for (i = 0; i < info->type_arguments->len; i++) {
8527                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8528
8529                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8530                         if (!type_args [i]) {
8531                                 g_free (type_args);
8532                                 return NULL;
8533                         }
8534                 }
8535
8536                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8537                 if (!the_type)
8538                         return NULL;
8539
8540                 instance = mono_reflection_bind_generic_parameters (
8541                         the_type, info->type_arguments->len, type_args);
8542
8543                 g_free (type_args);
8544                 if (!instance)
8545                         return NULL;
8546
8547                 klass = mono_class_from_mono_type (instance);
8548         }
8549
8550         for (mod = info->modifiers; mod; mod = mod->next) {
8551                 modval = GPOINTER_TO_UINT (mod->data);
8552                 if (!modval) { /* byref: must be last modifier */
8553                         return &klass->this_arg;
8554                 } else if (modval == -1) {
8555                         klass = mono_ptr_class_get (&klass->byval_arg);
8556                 } else if (modval == -2) {
8557                         bounded = TRUE;
8558                 } else { /* array rank */
8559                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8560                 }
8561         }
8562
8563         return &klass->byval_arg;
8564 }
8565
8566 /*
8567  * mono_reflection_get_type:
8568  * @image: a metadata context
8569  * @info: type description structure
8570  * @ignorecase: flag for case-insensitive string compares
8571  * @type_resolve: whenever type resolve was already tried
8572  *
8573  * Build a MonoType from the type description in @info.
8574  * 
8575  */
8576
8577 MonoType*
8578 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8579         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8580 }
8581
8582 static MonoType*
8583 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8584 {
8585         MonoReflectionAssemblyBuilder *abuilder;
8586         MonoType *type;
8587         int i;
8588
8589         mono_error_init (error);
8590         g_assert (assembly_is_dynamic (assembly));
8591         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8592         if (!abuilder)
8593                 return NULL;
8594
8595         /* Enumerate all modules */
8596
8597         type = NULL;
8598         if (abuilder->modules) {
8599                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8600                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8601                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8602                         if (type)
8603                                 break;
8604                         if (!mono_error_ok (error))
8605                                 return NULL;
8606                 }
8607         }
8608
8609         if (!type && abuilder->loaded_modules) {
8610                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8611                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8612                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8613                         if (type)
8614                                 break;
8615                         if (!mono_error_ok (error))
8616                                 return NULL;
8617                 }
8618         }
8619
8620         return type;
8621 }
8622         
8623 MonoType*
8624 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8625 {
8626         MonoError error;
8627         MonoType *type;
8628         MonoReflectionAssembly *assembly;
8629         GString *fullName;
8630         GList *mod;
8631
8632         if (image && image_is_dynamic (image))
8633                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8634         else {
8635                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8636         }
8637         if (!mono_error_ok (&error))
8638                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8639
8640         if (type)
8641                 return type;
8642         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8643                 return NULL;
8644
8645         if (type_resolve) {
8646                 if (*type_resolve) 
8647                         return NULL;
8648                 else
8649                         *type_resolve = TRUE;
8650         }
8651         
8652         /* Reconstruct the type name */
8653         fullName = g_string_new ("");
8654         if (info->name_space && (info->name_space [0] != '\0'))
8655                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8656         else
8657                 g_string_printf (fullName, "%s", info->name);
8658         for (mod = info->nested; mod; mod = mod->next)
8659                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8660
8661         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8662         mono_error_raise_exception (&error); /* FIXME don't raise here */
8663
8664         if (assembly) {
8665                 if (assembly_is_dynamic (assembly->assembly))
8666                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8667                                                                           info, ignorecase, &error);
8668                 else
8669                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8670                                                                   info, ignorecase, &error);
8671         }
8672         g_string_free (fullName, TRUE);
8673         if (!mono_error_ok (&error))
8674                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8675         return type;
8676 }
8677
8678 void
8679 mono_reflection_free_type_info (MonoTypeNameParse *info)
8680 {
8681         g_list_free (info->modifiers);
8682         g_list_free (info->nested);
8683
8684         if (info->type_arguments) {
8685                 int i;
8686
8687                 for (i = 0; i < info->type_arguments->len; i++) {
8688                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8689
8690                         mono_reflection_free_type_info (subinfo);
8691                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8692                         g_free (subinfo);
8693                 }
8694
8695                 g_ptr_array_free (info->type_arguments, TRUE);
8696         }
8697 }
8698
8699 /*
8700  * mono_reflection_type_from_name:
8701  * @name: type name.
8702  * @image: a metadata context (can be NULL).
8703  *
8704  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8705  * it defaults to get the type from @image or, if @image is NULL or loading
8706  * from it fails, uses corlib.
8707  * 
8708  */
8709 MonoType*
8710 mono_reflection_type_from_name (char *name, MonoImage *image)
8711 {
8712         MonoType *type = NULL;
8713         MonoTypeNameParse info;
8714         char *tmp;
8715
8716         /* Make a copy since parse_type modifies its argument */
8717         tmp = g_strdup (name);
8718         
8719         /*g_print ("requested type %s\n", str);*/
8720         if (mono_reflection_parse_type (tmp, &info)) {
8721                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8722         }
8723
8724         g_free (tmp);
8725         mono_reflection_free_type_info (&info);
8726         return type;
8727 }
8728
8729 /*
8730  * mono_reflection_get_token:
8731  *
8732  *   Return the metadata token of OBJ which should be an object
8733  * representing a metadata element.
8734  */
8735 guint32
8736 mono_reflection_get_token (MonoObject *obj)
8737 {
8738         MonoError error;
8739         MonoClass *klass;
8740         guint32 token = 0;
8741
8742         klass = obj->vtable->klass;
8743
8744         if (strcmp (klass->name, "MethodBuilder") == 0) {
8745                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8746
8747                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8748         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8749                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8750
8751                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8752         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8753                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8754
8755                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8756         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8757                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8758                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8759         } else if (strcmp (klass->name, "MonoType") == 0) {
8760                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8761                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8762                 MonoClass *mc = mono_class_from_mono_type (type);
8763                 if (!mono_class_init (mc))
8764                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8765
8766                 token = mc->type_token;
8767         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8768                    strcmp (klass->name, "MonoMethod") == 0 ||
8769                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8770                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8771                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8772                 if (m->method->is_inflated) {
8773                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8774                         return inflated->declaring->token;
8775                 } else {
8776                         token = m->method->token;
8777                 }
8778         } else if (strcmp (klass->name, "MonoField") == 0) {
8779                 MonoReflectionField *f = (MonoReflectionField*)obj;
8780
8781                 if (is_field_on_inst (f->field)) {
8782                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8783
8784                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8785                                 int field_index = f->field - dgclass->fields;
8786                                 MonoObject *obj;
8787
8788                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8789                                 obj = dgclass->field_objects [field_index];
8790                                 return mono_reflection_get_token (obj);
8791                         }
8792                 }
8793                 token = mono_class_get_field_token (f->field);
8794         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8795                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8796
8797                 token = mono_class_get_property_token (p->property);
8798         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8799                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8800
8801                 token = mono_class_get_event_token (p->event);
8802         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8803                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8804                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8805                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8806
8807                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8808         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8809                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8810
8811                 token = m->token;
8812         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8813                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8814         } else {
8815                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8816                 MonoException *ex = mono_get_exception_not_implemented (msg);
8817                 g_free (msg);
8818                 mono_raise_exception (ex);
8819         }
8820
8821         return token;
8822 }
8823
8824 static MonoClass*
8825 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8826 {
8827         char *n;
8828         MonoType *t;
8829         int slen = mono_metadata_decode_value (p, &p);
8830
8831         mono_error_init (error);
8832
8833         n = (char *)g_memdup (p, slen + 1);
8834         n [slen] = 0;
8835         t = mono_reflection_type_from_name (n, image);
8836         if (!t) {
8837                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8838                 /* We don't free n, it's consumed by mono_error */
8839                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8840                 return NULL;
8841         }
8842         g_free (n);
8843         p += slen;
8844         *end = p;
8845         return mono_class_from_mono_type (t);
8846 }
8847
8848 static void*
8849 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8850 {
8851         int slen, type = t->type;
8852         MonoClass *tklass = t->data.klass;
8853
8854         mono_error_init (error);
8855
8856 handle_enum:
8857         switch (type) {
8858         case MONO_TYPE_U1:
8859         case MONO_TYPE_I1:
8860         case MONO_TYPE_BOOLEAN: {
8861                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8862                 *bval = *p;
8863                 *end = p + 1;
8864                 return bval;
8865         }
8866         case MONO_TYPE_CHAR:
8867         case MONO_TYPE_U2:
8868         case MONO_TYPE_I2: {
8869                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8870                 *val = read16 (p);
8871                 *end = p + 2;
8872                 return val;
8873         }
8874 #if SIZEOF_VOID_P == 4
8875         case MONO_TYPE_U:
8876         case MONO_TYPE_I:
8877 #endif
8878         case MONO_TYPE_R4:
8879         case MONO_TYPE_U4:
8880         case MONO_TYPE_I4: {
8881                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8882                 *val = read32 (p);
8883                 *end = p + 4;
8884                 return val;
8885         }
8886 #if SIZEOF_VOID_P == 8
8887         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8888         case MONO_TYPE_I:
8889 #endif
8890         case MONO_TYPE_U8:
8891         case MONO_TYPE_I8: {
8892                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8893                 *val = read64 (p);
8894                 *end = p + 8;
8895                 return val;
8896         }
8897         case MONO_TYPE_R8: {
8898                 double *val = (double *)g_malloc (sizeof (double));
8899                 readr8 (p, val);
8900                 *end = p + 8;
8901                 return val;
8902         }
8903         case MONO_TYPE_VALUETYPE:
8904                 if (t->data.klass->enumtype) {
8905                         type = mono_class_enum_basetype (t->data.klass)->type;
8906                         goto handle_enum;
8907                 } else {
8908                         MonoClass *k =  t->data.klass;
8909                         
8910                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8911                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8912                                 *val = read64 (p);
8913                                 *end = p + 8;
8914                                 return val;
8915                         }
8916                 }
8917                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8918                 break;
8919                 
8920         case MONO_TYPE_STRING:
8921                 if (*p == (char)0xFF) {
8922                         *end = p + 1;
8923                         return NULL;
8924                 }
8925                 slen = mono_metadata_decode_value (p, &p);
8926                 *end = p + slen;
8927                 return mono_string_new_len (mono_domain_get (), p, slen);
8928         case MONO_TYPE_CLASS: {
8929                 MonoReflectionType *rt;
8930                 char *n;
8931                 MonoType *t;
8932                 if (*p == (char)0xFF) {
8933                         *end = p + 1;
8934                         return NULL;
8935                 }
8936 handle_type:
8937                 slen = mono_metadata_decode_value (p, &p);
8938                 n = (char *)g_memdup (p, slen + 1);
8939                 n [slen] = 0;
8940                 t = mono_reflection_type_from_name (n, image);
8941                 if (!t) {
8942                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8943                         /* We don't free n, it's consumed by mono_error */
8944                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8945                         return NULL;
8946                 }
8947                 g_free (n);
8948                 *end = p + slen;
8949
8950                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8951                 if (!mono_error_ok (error))
8952                         return NULL;
8953
8954                 return rt;
8955         }
8956         case MONO_TYPE_OBJECT: {
8957                 char subt = *p++;
8958                 MonoObject *obj;
8959                 MonoClass *subc = NULL;
8960                 void *val;
8961
8962                 if (subt == 0x50) {
8963                         goto handle_type;
8964                 } else if (subt == 0x0E) {
8965                         type = MONO_TYPE_STRING;
8966                         goto handle_enum;
8967                 } else if (subt == 0x1D) {
8968                         MonoType simple_type = {{0}};
8969                         int etype = *p;
8970                         p ++;
8971
8972                         type = MONO_TYPE_SZARRAY;
8973                         if (etype == 0x50) {
8974                                 tklass = mono_defaults.systemtype_class;
8975                         } else if (etype == 0x55) {
8976                                 tklass = load_cattr_enum_type (image, p, &p, error);
8977                                 if (!mono_error_ok (error))
8978                                         return NULL;
8979                         } else {
8980                                 if (etype == 0x51)
8981                                         /* See Partition II, Appendix B3 */
8982                                         etype = MONO_TYPE_OBJECT;
8983                                 simple_type.type = (MonoTypeEnum)etype;
8984                                 tklass = mono_class_from_mono_type (&simple_type);
8985                         }
8986                         goto handle_enum;
8987                 } else if (subt == 0x55) {
8988                         char *n;
8989                         MonoType *t;
8990                         slen = mono_metadata_decode_value (p, &p);
8991                         n = (char *)g_memdup (p, slen + 1);
8992                         n [slen] = 0;
8993                         t = mono_reflection_type_from_name (n, image);
8994                         if (!t) {
8995                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8996                                 /* We don't free n, it's consumed by mono_error */
8997                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8998                                 return NULL;
8999                         }
9000                         g_free (n);
9001                         p += slen;
9002                         subc = mono_class_from_mono_type (t);
9003                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
9004                         MonoType simple_type = {{0}};
9005                         simple_type.type = (MonoTypeEnum)subt;
9006                         subc = mono_class_from_mono_type (&simple_type);
9007                 } else {
9008                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
9009                 }
9010                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
9011                 obj = NULL;
9012                 if (mono_error_ok (error)) {
9013                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
9014                         g_assert (!subc->has_references);
9015                         if (mono_error_ok (error))
9016                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9017                 }
9018
9019                 g_free (val);
9020                 return obj;
9021         }
9022         case MONO_TYPE_SZARRAY: {
9023                 MonoArray *arr;
9024                 guint32 i, alen, basetype;
9025                 alen = read32 (p);
9026                 p += 4;
9027                 if (alen == 0xffffffff) {
9028                         *end = p;
9029                         return NULL;
9030                 }
9031                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9032                 basetype = tklass->byval_arg.type;
9033                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9034                         basetype = mono_class_enum_basetype (tklass)->type;
9035                 switch (basetype)
9036                 {
9037                         case MONO_TYPE_U1:
9038                         case MONO_TYPE_I1:
9039                         case MONO_TYPE_BOOLEAN:
9040                                 for (i = 0; i < alen; i++) {
9041                                         MonoBoolean val = *p++;
9042                                         mono_array_set (arr, MonoBoolean, i, val);
9043                                 }
9044                                 break;
9045                         case MONO_TYPE_CHAR:
9046                         case MONO_TYPE_U2:
9047                         case MONO_TYPE_I2:
9048                                 for (i = 0; i < alen; i++) {
9049                                         guint16 val = read16 (p);
9050                                         mono_array_set (arr, guint16, i, val);
9051                                         p += 2;
9052                                 }
9053                                 break;
9054                         case MONO_TYPE_R4:
9055                         case MONO_TYPE_U4:
9056                         case MONO_TYPE_I4:
9057                                 for (i = 0; i < alen; i++) {
9058                                         guint32 val = read32 (p);
9059                                         mono_array_set (arr, guint32, i, val);
9060                                         p += 4;
9061                                 }
9062                                 break;
9063                         case MONO_TYPE_R8:
9064                                 for (i = 0; i < alen; i++) {
9065                                         double val;
9066                                         readr8 (p, &val);
9067                                         mono_array_set (arr, double, i, val);
9068                                         p += 8;
9069                                 }
9070                                 break;
9071                         case MONO_TYPE_U8:
9072                         case MONO_TYPE_I8:
9073                                 for (i = 0; i < alen; i++) {
9074                                         guint64 val = read64 (p);
9075                                         mono_array_set (arr, guint64, i, val);
9076                                         p += 8;
9077                                 }
9078                                 break;
9079                         case MONO_TYPE_CLASS:
9080                         case MONO_TYPE_OBJECT:
9081                         case MONO_TYPE_STRING:
9082                         case MONO_TYPE_SZARRAY:
9083                                 for (i = 0; i < alen; i++) {
9084                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9085                                         if (!mono_error_ok (error))
9086                                                 return NULL;
9087                                         mono_array_setref (arr, i, item);
9088                                 }
9089                                 break;
9090                         default:
9091                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9092                 }
9093                 *end=p;
9094                 return arr;
9095         }
9096         default:
9097                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9098         }
9099         return NULL;
9100 }
9101
9102 static MonoObject*
9103 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9104 {
9105         static MonoMethod *ctor;
9106         MonoObject *retval;
9107         void *params [2], *unboxed;
9108
9109         mono_error_init (error);
9110
9111         if (!ctor)
9112                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9113         
9114         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9115         return_val_if_nok (error, NULL);
9116
9117         params [1] = val;
9118         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9119         return_val_if_nok (error, NULL);
9120         unboxed = mono_object_unbox (retval);
9121
9122         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9123         return_val_if_nok (error, NULL);
9124
9125         return retval;
9126 }
9127
9128 static MonoObject*
9129 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9130 {
9131         static MonoMethod *ctor;
9132         MonoObject *retval;
9133         void *unboxed, *params [2];
9134
9135         mono_error_init (error);
9136
9137         if (!ctor)
9138                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9139
9140         params [0] = minfo;
9141         params [1] = typedarg;
9142         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9143         return_val_if_nok (error, NULL);
9144
9145         unboxed = mono_object_unbox (retval);
9146
9147         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9148         return_val_if_nok (error, NULL);
9149
9150         return retval;
9151 }
9152
9153 static gboolean
9154 type_is_reference (MonoType *type)
9155 {
9156         switch (type->type) {
9157         case MONO_TYPE_BOOLEAN:
9158         case MONO_TYPE_CHAR:
9159         case MONO_TYPE_U:
9160         case MONO_TYPE_I:
9161         case MONO_TYPE_U1:
9162         case MONO_TYPE_I1:
9163         case MONO_TYPE_U2:
9164         case MONO_TYPE_I2:
9165         case MONO_TYPE_U4:
9166         case MONO_TYPE_I4:
9167         case MONO_TYPE_U8:
9168         case MONO_TYPE_I8:
9169         case MONO_TYPE_R8:
9170         case MONO_TYPE_R4:
9171         case MONO_TYPE_VALUETYPE:
9172                 return FALSE;
9173         default:
9174                 return TRUE;
9175         }
9176 }
9177
9178 static void
9179 free_param_data (MonoMethodSignature *sig, void **params) {
9180         int i;
9181         for (i = 0; i < sig->param_count; ++i) {
9182                 if (!type_is_reference (sig->params [i]))
9183                         g_free (params [i]);
9184         }
9185 }
9186
9187 /*
9188  * Find the field index in the metadata FieldDef table.
9189  */
9190 static guint32
9191 find_field_index (MonoClass *klass, MonoClassField *field) {
9192         int i;
9193
9194         for (i = 0; i < klass->field.count; ++i) {
9195                 if (field == &klass->fields [i])
9196                         return klass->field.first + 1 + i;
9197         }
9198         return 0;
9199 }
9200
9201 /*
9202  * Find the property index in the metadata Property table.
9203  */
9204 static guint32
9205 find_property_index (MonoClass *klass, MonoProperty *property) {
9206         int i;
9207
9208         for (i = 0; i < klass->ext->property.count; ++i) {
9209                 if (property == &klass->ext->properties [i])
9210                         return klass->ext->property.first + 1 + i;
9211         }
9212         return 0;
9213 }
9214
9215 /*
9216  * Find the event index in the metadata Event table.
9217  */
9218 static guint32
9219 find_event_index (MonoClass *klass, MonoEvent *event) {
9220         int i;
9221
9222         for (i = 0; i < klass->ext->event.count; ++i) {
9223                 if (event == &klass->ext->events [i])
9224                         return klass->ext->event.first + 1 + i;
9225         }
9226         return 0;
9227 }
9228
9229 static MonoObject*
9230 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9231 {
9232         const char *p = (const char*)data;
9233         const char *named;
9234         guint32 i, j, num_named;
9235         MonoObject *attr;
9236         void *params_buf [32];
9237         void **params = NULL;
9238         MonoMethodSignature *sig;
9239         MonoObject *exc = NULL;
9240
9241         mono_error_init (error);
9242
9243         mono_class_init (method->klass);
9244
9245         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9246                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9247                 return NULL;
9248         }
9249
9250         if (len == 0) {
9251                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9252                 if (!mono_error_ok (error)) return NULL;
9253
9254                 mono_runtime_invoke_checked (method, attr, NULL, error);
9255                 if (!mono_error_ok (error))
9256                         return NULL;
9257
9258                 return attr;
9259         }
9260
9261         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9262                 return NULL;
9263
9264         /*g_print ("got attr %s\n", method->klass->name);*/
9265
9266         sig = mono_method_signature (method);
9267         if (sig->param_count < 32) {
9268                 params = params_buf;
9269                 memset (params, 0, sizeof (void*) * sig->param_count);
9270         } else {
9271                 /* Allocate using GC so it gets GC tracking */
9272                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9273         }
9274
9275         /* skip prolog */
9276         p += 2;
9277         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9278                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9279                 if (!mono_error_ok (error))
9280                         goto fail;
9281         }
9282
9283         named = p;
9284         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9285         if (!mono_error_ok (error)) goto fail;
9286
9287         mono_runtime_try_invoke (method, attr, params, &exc, error);
9288         if (!mono_error_ok (error))
9289                 goto fail;
9290         if (exc)
9291                 goto fail;
9292
9293         num_named = read16 (named);
9294         named += 2;
9295         for (j = 0; j < num_named; j++) {
9296                 gint name_len;
9297                 char *name, named_type, data_type;
9298                 named_type = *named++;
9299                 data_type = *named++; /* type of data */
9300                 if (data_type == MONO_TYPE_SZARRAY)
9301                         data_type = *named++;
9302                 if (data_type == MONO_TYPE_ENUM) {
9303                         gint type_len;
9304                         char *type_name;
9305                         type_len = mono_metadata_decode_blob_size (named, &named);
9306                         type_name = (char *)g_malloc (type_len + 1);
9307                         memcpy (type_name, named, type_len);
9308                         type_name [type_len] = 0;
9309                         named += type_len;
9310                         /* FIXME: lookup the type and check type consistency */
9311                         g_free (type_name);
9312                 }
9313                 name_len = mono_metadata_decode_blob_size (named, &named);
9314                 name = (char *)g_malloc (name_len + 1);
9315                 memcpy (name, named, name_len);
9316                 name [name_len] = 0;
9317                 named += name_len;
9318                 if (named_type == 0x53) {
9319                         MonoClassField *field;
9320                         void *val;
9321
9322                         /* how this fail is a blackbox */
9323                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9324                         if (!field) {
9325                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9326                                 g_free (name);
9327                                 goto fail;
9328                         }
9329
9330                         val = load_cattr_value (image, field->type, named, &named, error);
9331                         if (!mono_error_ok (error)) {
9332                                 g_free (name);
9333                                 if (!type_is_reference (field->type))
9334                                         g_free (val);
9335                                 goto fail;
9336                         }
9337
9338                         mono_field_set_value (attr, field, val);
9339                         if (!type_is_reference (field->type))
9340                                 g_free (val);
9341                 } else if (named_type == 0x54) {
9342                         MonoProperty *prop;
9343                         void *pparams [1];
9344                         MonoType *prop_type;
9345
9346                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9347
9348                         if (!prop) {
9349                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9350                                 g_free (name);
9351                                 goto fail;
9352                         }
9353
9354                         if (!prop->set) {
9355                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9356                                 g_free (name);
9357                                 goto fail;
9358                         }
9359
9360                         /* can we have more that 1 arg in a custom attr named property? */
9361                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9362                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9363
9364                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9365                         if (!mono_error_ok (error)) {
9366                                 g_free (name);
9367                                 if (!type_is_reference (prop_type))
9368                                         g_free (pparams [0]);
9369                                 goto fail;
9370                         }
9371
9372
9373                         mono_property_set_value (prop, attr, pparams, NULL);
9374                         if (!type_is_reference (prop_type))
9375                                 g_free (pparams [0]);
9376                 }
9377                 g_free (name);
9378         }
9379
9380         free_param_data (method->signature, params);
9381         if (params != params_buf)
9382                 mono_gc_free_fixed (params);
9383
9384         return attr;
9385
9386 fail:
9387         free_param_data (method->signature, params);
9388         if (params != params_buf)
9389                 mono_gc_free_fixed (params);
9390         if (exc)
9391                 mono_raise_exception ((MonoException*)exc);
9392         return NULL;
9393 }
9394         
9395 /*
9396  * mono_reflection_create_custom_attr_data_args:
9397  *
9398  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9399  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9400  * NAMED_ARG_INFO will contain information about the named arguments.
9401  */
9402 void
9403 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)
9404 {
9405         MonoArray *typedargs, *namedargs;
9406         MonoClass *attrklass;
9407         MonoDomain *domain;
9408         const char *p = (const char*)data;
9409         const char *named;
9410         guint32 i, j, num_named;
9411         CattrNamedArg *arginfo = NULL;
9412
9413         *typed_args = NULL;
9414         *named_args = NULL;
9415         *named_arg_info = NULL;
9416
9417         mono_error_init (error);
9418
9419         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9420                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9421                 return;
9422         }
9423
9424         mono_class_init (method->klass);
9425         
9426         domain = mono_domain_get ();
9427
9428         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9429                 return;
9430
9431         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9432         
9433         /* skip prolog */
9434         p += 2;
9435         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9436                 MonoObject *obj;
9437                 void *val;
9438
9439                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9440                 if (!mono_error_ok (error)) {
9441                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9442                                 g_free (val);
9443                         return;
9444                 }
9445
9446                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9447                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9448                 mono_array_setref (typedargs, i, obj);
9449
9450                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9451                         g_free (val);
9452         }
9453
9454         named = p;
9455         num_named = read16 (named);
9456         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9457         named += 2;
9458         attrklass = method->klass;
9459
9460         arginfo = g_new0 (CattrNamedArg, num_named);
9461         *named_arg_info = arginfo;
9462
9463         for (j = 0; j < num_named; j++) {
9464                 gint name_len;
9465                 char *name, named_type, data_type;
9466                 named_type = *named++;
9467                 data_type = *named++; /* type of data */
9468                 if (data_type == MONO_TYPE_SZARRAY)
9469                         data_type = *named++;
9470                 if (data_type == MONO_TYPE_ENUM) {
9471                         gint type_len;
9472                         char *type_name;
9473                         type_len = mono_metadata_decode_blob_size (named, &named);
9474                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9475                                 goto fail;
9476
9477                         type_name = (char *)g_malloc (type_len + 1);
9478                         memcpy (type_name, named, type_len);
9479                         type_name [type_len] = 0;
9480                         named += type_len;
9481                         /* FIXME: lookup the type and check type consistency */
9482                         g_free (type_name);
9483                 }
9484                 name_len = mono_metadata_decode_blob_size (named, &named);
9485                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9486                         goto fail;
9487                 name = (char *)g_malloc (name_len + 1);
9488                 memcpy (name, named, name_len);
9489                 name [name_len] = 0;
9490                 named += name_len;
9491                 if (named_type == 0x53) {
9492                         MonoObject *obj;
9493                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9494                         void *val;
9495
9496                         if (!field) {
9497                                 g_free (name);
9498                                 goto fail;
9499                         }
9500
9501                         arginfo [j].type = field->type;
9502                         arginfo [j].field = field;
9503
9504                         val = load_cattr_value (image, field->type, named, &named, error);
9505                         if (!mono_error_ok (error)) {
9506                                 if (!type_is_reference (field->type))
9507                                         g_free (val);
9508                                 g_free (name);
9509                                 return;
9510                         }
9511
9512                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9513                         mono_array_setref (namedargs, j, obj);
9514                         if (!type_is_reference (field->type))
9515                                 g_free (val);
9516                 } else if (named_type == 0x54) {
9517                         MonoObject *obj;
9518                         MonoType *prop_type;
9519                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9520                         void *val;
9521
9522                         if (!prop || !prop->set) {
9523                                 g_free (name);
9524                                 goto fail;
9525                         }
9526
9527                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9528                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9529
9530                         arginfo [j].type = prop_type;
9531                         arginfo [j].prop = prop;
9532
9533                         val = load_cattr_value (image, prop_type, named, &named, error);
9534                         if (!mono_error_ok (error)) {
9535                                 if (!type_is_reference (prop_type))
9536                                         g_free (val);
9537                                 g_free (name);
9538                                 return;
9539                         }
9540
9541                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9542                         mono_array_setref (namedargs, j, obj);
9543                         if (!type_is_reference (prop_type))
9544                                 g_free (val);
9545                 }
9546                 g_free (name);
9547         }
9548
9549         *typed_args = typedargs;
9550         *named_args = namedargs;
9551         return;
9552 fail:
9553         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9554         g_free (arginfo);
9555         *named_arg_info = NULL;
9556 }
9557
9558 void
9559 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9560 {
9561         MonoDomain *domain;
9562         MonoArray *typedargs, *namedargs;
9563         MonoImage *image;
9564         MonoMethod *method;
9565         CattrNamedArg *arginfo = NULL;
9566         MonoError error;
9567         int i;
9568
9569         mono_error_init (&error);
9570
9571         *ctor_args = NULL;
9572         *named_args = NULL;
9573
9574         if (len == 0)
9575                 return;
9576
9577         image = assembly->assembly->image;
9578         method = ref_method->method;
9579         domain = mono_object_domain (ref_method);
9580
9581         if (!mono_class_init (method->klass))
9582                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9583
9584         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9585         if (!mono_error_ok (&error))
9586                 goto leave;
9587
9588         if (mono_loader_get_last_error ()) {
9589                 mono_error_set_from_loader_error (&error);
9590                 goto leave;
9591         }
9592
9593         if (!typedargs || !namedargs)
9594                 goto leave;
9595
9596         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9597                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9598                 MonoObject *typedarg;
9599
9600                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9601                 if (!is_ok (&error))
9602                         goto leave;
9603                 mono_array_setref (typedargs, i, typedarg);
9604         }
9605
9606         for (i = 0; i < mono_array_length (namedargs); ++i) {
9607                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9608                 MonoObject *typedarg, *namedarg, *minfo;
9609
9610                 if (arginfo [i].prop) {
9611                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9612                         if (!minfo)
9613                                 goto leave;
9614                 } else {
9615                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9616                         if (!mono_error_ok (&error))
9617                                 goto leave;
9618                 }
9619
9620                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9621                 if (!is_ok (&error))
9622                         goto leave;
9623                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9624                 if (!is_ok (&error))
9625                         goto leave;
9626
9627                 mono_array_setref (namedargs, i, namedarg);
9628         }
9629
9630         *ctor_args = typedargs;
9631         *named_args = namedargs;
9632 leave:
9633         g_free (arginfo);
9634         mono_error_raise_exception (&error);
9635
9636 }
9637
9638 static MonoObject*
9639 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9640 {
9641         static MonoMethod *ctor;
9642
9643         MonoDomain *domain;
9644         MonoObject *attr;
9645         void *params [4];
9646
9647         mono_error_init (error);
9648
9649         g_assert (image->assembly);
9650
9651         if (!ctor)
9652                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9653
9654         domain = mono_domain_get ();
9655         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9656         return_val_if_nok (error, NULL);
9657         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9658         return_val_if_nok (error, NULL);
9659         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9660         return_val_if_nok (error, NULL);
9661         params [2] = (gpointer)&cattr->data;
9662         params [3] = &cattr->data_size;
9663
9664         mono_runtime_invoke_checked (ctor, attr, params, error);
9665         return_val_if_nok (error, NULL);
9666         return attr;
9667 }
9668
9669 static MonoArray*
9670 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9671 {
9672         MonoArray *result;
9673         MonoObject *attr;
9674         int i, n;
9675
9676         mono_error_init (error);
9677
9678         n = 0;
9679         for (i = 0; i < cinfo->num_attrs; ++i) {
9680                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9681                         n ++;
9682         }
9683
9684         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9685         n = 0;
9686         for (i = 0; i < cinfo->num_attrs; ++i) {
9687                 if (!cinfo->attrs [i].ctor) {
9688                         /* The cattr type is not finished yet */
9689                         /* We should include the type name but cinfo doesn't contain it */
9690                         mono_error_set_type_load_name (error, NULL, NULL, "");
9691                         return NULL;
9692                 }
9693                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9694                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9695                         if (!mono_error_ok (error))
9696                                 return result;
9697                         mono_array_setref (result, n, attr);
9698                         n ++;
9699                 }
9700         }
9701         return result;
9702 }
9703
9704 MonoArray*
9705 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9706 {
9707         MonoError error;
9708         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9709         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9710
9711         return result;
9712 }
9713
9714 static MonoArray*
9715 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9716 {
9717         MonoArray *result;
9718         MonoObject *attr;
9719         int i;
9720         
9721         mono_error_init (error);
9722         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9723         for (i = 0; i < cinfo->num_attrs; ++i) {
9724                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9725                 return_val_if_nok (error, NULL);
9726                 mono_array_setref (result, i, attr);
9727         }
9728         return result;
9729 }
9730
9731 /**
9732  * mono_custom_attrs_from_index:
9733  *
9734  * Returns: NULL if no attributes are found or if a loading error occurs.
9735  */
9736 MonoCustomAttrInfo*
9737 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9738 {
9739         MonoError error;
9740         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9741         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9742         return result;
9743 }
9744 /**
9745  * mono_custom_attrs_from_index_checked:
9746  *
9747  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9748  */
9749 MonoCustomAttrInfo*
9750 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9751 {
9752         guint32 mtoken, i, len;
9753         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9754         MonoTableInfo *ca;
9755         MonoCustomAttrInfo *ainfo;
9756         GList *tmp, *list = NULL;
9757         const char *data;
9758         MonoCustomAttrEntry* attr;
9759
9760         mono_error_init (error);
9761
9762         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9763
9764         i = mono_metadata_custom_attrs_from_index (image, idx);
9765         if (!i)
9766                 return NULL;
9767         i --;
9768         while (i < ca->rows) {
9769                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9770                         break;
9771                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9772                 ++i;
9773         }
9774         len = g_list_length (list);
9775         if (!len)
9776                 return NULL;
9777         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9778         ainfo->num_attrs = len;
9779         ainfo->image = image;
9780         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9781                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9782                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9783                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9784                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9785                         mtoken |= MONO_TOKEN_METHOD_DEF;
9786                         break;
9787                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9788                         mtoken |= MONO_TOKEN_MEMBER_REF;
9789                         break;
9790                 default:
9791                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9792                         break;
9793                 }
9794                 attr = &ainfo->attrs [i - 1];
9795                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9796                 if (!attr->ctor) {
9797                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9798                         g_list_free (list);
9799                         g_free (ainfo);
9800                         return NULL;
9801                 }
9802
9803                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9804                         /*FIXME raising an exception here doesn't make any sense*/
9805                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9806                         g_list_free (list);
9807                         g_free (ainfo);
9808                         return NULL;
9809                 }
9810                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9811                 attr->data_size = mono_metadata_decode_value (data, &data);
9812                 attr->data = (guchar*)data;
9813         }
9814         g_list_free (list);
9815
9816         return ainfo;
9817 }
9818
9819 MonoCustomAttrInfo*
9820 mono_custom_attrs_from_method (MonoMethod *method)
9821 {
9822         MonoError error;
9823         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9824         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9825         return result;
9826 }
9827
9828 MonoCustomAttrInfo*
9829 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9830 {
9831         guint32 idx;
9832
9833         mono_error_init (error);
9834
9835         /*
9836          * An instantiated method has the same cattrs as the generic method definition.
9837          *
9838          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9839          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9840          */
9841         if (method->is_inflated)
9842                 method = ((MonoMethodInflated *) method)->declaring;
9843         
9844         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9845                 return lookup_custom_attr (method->klass->image, method);
9846
9847         if (!method->token)
9848                 /* Synthetic methods */
9849                 return NULL;
9850
9851         idx = mono_method_get_index (method);
9852         idx <<= MONO_CUSTOM_ATTR_BITS;
9853         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9854         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9855 }
9856
9857 MonoCustomAttrInfo*
9858 mono_custom_attrs_from_class (MonoClass *klass)
9859 {
9860         MonoError error;
9861         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9862         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9863         return result;
9864 }
9865
9866 MonoCustomAttrInfo*
9867 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9868 {
9869         guint32 idx;
9870
9871         mono_error_init (error);
9872
9873         if (klass->generic_class)
9874                 klass = klass->generic_class->container_class;
9875
9876         if (image_is_dynamic (klass->image))
9877                 return lookup_custom_attr (klass->image, klass);
9878
9879         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9880                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9881                 idx <<= MONO_CUSTOM_ATTR_BITS;
9882                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9883         } else {
9884                 idx = mono_metadata_token_index (klass->type_token);
9885                 idx <<= MONO_CUSTOM_ATTR_BITS;
9886                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9887         }
9888         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9889 }
9890
9891 MonoCustomAttrInfo*
9892 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9893 {
9894         MonoError error;
9895         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9896         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9897         return result;
9898 }
9899
9900 MonoCustomAttrInfo*
9901 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9902 {
9903         guint32 idx;
9904         
9905         mono_error_init (error);
9906
9907         if (image_is_dynamic (assembly->image))
9908                 return lookup_custom_attr (assembly->image, assembly);
9909         idx = 1; /* there is only one assembly */
9910         idx <<= MONO_CUSTOM_ATTR_BITS;
9911         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9912         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9913 }
9914
9915 static MonoCustomAttrInfo*
9916 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9917 {
9918         guint32 idx;
9919         
9920         if (image_is_dynamic (image))
9921                 return lookup_custom_attr (image, image);
9922         idx = 1; /* there is only one module */
9923         idx <<= MONO_CUSTOM_ATTR_BITS;
9924         idx |= MONO_CUSTOM_ATTR_MODULE;
9925         return mono_custom_attrs_from_index_checked (image, idx, error);
9926 }
9927
9928 MonoCustomAttrInfo*
9929 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9930 {
9931         MonoError error;
9932         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9933         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9934         return result;
9935 }
9936
9937 MonoCustomAttrInfo*
9938 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9939 {
9940         guint32 idx;
9941         
9942         if (image_is_dynamic (klass->image)) {
9943                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9944                 return lookup_custom_attr (klass->image, property);
9945         }
9946         idx = find_property_index (klass, property);
9947         idx <<= MONO_CUSTOM_ATTR_BITS;
9948         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9949         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9950 }
9951
9952 MonoCustomAttrInfo*
9953 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9954 {
9955         MonoError error;
9956         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9957         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9958         return result;
9959 }
9960
9961 MonoCustomAttrInfo*
9962 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9963 {
9964         guint32 idx;
9965         
9966         if (image_is_dynamic (klass->image)) {
9967                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9968                 return lookup_custom_attr (klass->image, event);
9969         }
9970         idx = find_event_index (klass, event);
9971         idx <<= MONO_CUSTOM_ATTR_BITS;
9972         idx |= MONO_CUSTOM_ATTR_EVENT;
9973         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9974 }
9975
9976 MonoCustomAttrInfo*
9977 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9978 {
9979         MonoError error;
9980         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9981         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9982         return result;
9983 }
9984
9985 MonoCustomAttrInfo*
9986 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9987 {
9988         guint32 idx;
9989         mono_error_init (error);
9990
9991         if (image_is_dynamic (klass->image)) {
9992                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9993                 return lookup_custom_attr (klass->image, field);
9994         }
9995         idx = find_field_index (klass, field);
9996         idx <<= MONO_CUSTOM_ATTR_BITS;
9997         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9998         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9999 }
10000
10001 /**
10002  * mono_custom_attrs_from_param:
10003  * @method: handle to the method that we want to retrieve custom parameter information from
10004  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10005  *
10006  * The result must be released with mono_custom_attrs_free().
10007  *
10008  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
10009  */
10010 MonoCustomAttrInfo*
10011 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
10012 {
10013         MonoError error;
10014         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
10015         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
10016         return result;
10017 }
10018
10019 /**
10020  * mono_custom_attrs_from_param_checked:
10021  * @method: handle to the method that we want to retrieve custom parameter information from
10022  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10023  * @error: set on error
10024  *
10025  * The result must be released with mono_custom_attrs_free().
10026  *
10027  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10028  */
10029 MonoCustomAttrInfo*
10030 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10031 {
10032         MonoTableInfo *ca;
10033         guint32 i, idx, method_index;
10034         guint32 param_list, param_last, param_pos, found;
10035         MonoImage *image;
10036         MonoReflectionMethodAux *aux;
10037
10038         mono_error_init (error);
10039
10040         /*
10041          * An instantiated method has the same cattrs as the generic method definition.
10042          *
10043          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10044          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10045          */
10046         if (method->is_inflated)
10047                 method = ((MonoMethodInflated *) method)->declaring;
10048
10049         if (image_is_dynamic (method->klass->image)) {
10050                 MonoCustomAttrInfo *res, *ainfo;
10051                 int size;
10052
10053                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10054                 if (!aux || !aux->param_cattr)
10055                         return NULL;
10056
10057                 /* Need to copy since it will be freed later */
10058                 ainfo = aux->param_cattr [param];
10059                 if (!ainfo)
10060                         return NULL;
10061                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10062                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10063                 memcpy (res, ainfo, size);
10064                 return res;
10065         }
10066
10067         image = method->klass->image;
10068         method_index = mono_method_get_index (method);
10069         if (!method_index)
10070                 return NULL;
10071         ca = &image->tables [MONO_TABLE_METHOD];
10072
10073         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10074         if (method_index == ca->rows) {
10075                 ca = &image->tables [MONO_TABLE_PARAM];
10076                 param_last = ca->rows + 1;
10077         } else {
10078                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10079                 ca = &image->tables [MONO_TABLE_PARAM];
10080         }
10081         found = FALSE;
10082         for (i = param_list; i < param_last; ++i) {
10083                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10084                 if (param_pos == param) {
10085                         found = TRUE;
10086                         break;
10087                 }
10088         }
10089         if (!found)
10090                 return NULL;
10091         idx = i;
10092         idx <<= MONO_CUSTOM_ATTR_BITS;
10093         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10094         return mono_custom_attrs_from_index_checked (image, idx, error);
10095 }
10096
10097 gboolean
10098 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10099 {
10100         int i;
10101         MonoClass *klass;
10102         for (i = 0; i < ainfo->num_attrs; ++i) {
10103                 klass = ainfo->attrs [i].ctor->klass;
10104                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10105                         return TRUE;
10106         }
10107         return FALSE;
10108 }
10109
10110 MonoObject*
10111 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10112 {
10113         MonoError error;
10114         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10115         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10116         return res;
10117 }
10118
10119 MonoObject*
10120 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10121 {
10122         int i, attr_index;
10123         MonoClass *klass;
10124         MonoArray *attrs;
10125
10126         mono_error_init (error);
10127
10128         attr_index = -1;
10129         for (i = 0; i < ainfo->num_attrs; ++i) {
10130                 klass = ainfo->attrs [i].ctor->klass;
10131                 if (mono_class_has_parent (klass, attr_klass)) {
10132                         attr_index = i;
10133                         break;
10134                 }
10135         }
10136         if (attr_index == -1)
10137                 return NULL;
10138
10139         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10140         if (!mono_error_ok (error))
10141                 return NULL;
10142         return mono_array_get (attrs, MonoObject*, attr_index);
10143 }
10144
10145 /*
10146  * mono_reflection_get_custom_attrs_info:
10147  * @obj: a reflection object handle
10148  *
10149  * Return the custom attribute info for attributes defined for the
10150  * reflection handle @obj. The objects.
10151  *
10152  * FIXME this function leaks like a sieve for SRE objects.
10153  */
10154 MonoCustomAttrInfo*
10155 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10156 {
10157         MonoError error;
10158         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10159         mono_error_assert_ok (&error);
10160         return result;
10161 }
10162
10163 /**
10164  * mono_reflection_get_custom_attrs_info_checked:
10165  * @obj: a reflection object handle
10166  * @error: set on error
10167  *
10168  * Return the custom attribute info for attributes defined for the
10169  * reflection handle @obj. The objects.
10170  *
10171  * On failure returns NULL and sets @error.
10172  *
10173  * FIXME this function leaks like a sieve for SRE objects.
10174  */
10175 MonoCustomAttrInfo*
10176 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10177 {
10178         MonoClass *klass;
10179         MonoCustomAttrInfo *cinfo = NULL;
10180         
10181         mono_error_init (error);
10182
10183         klass = obj->vtable->klass;
10184         if (klass == mono_defaults.monotype_class) {
10185                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10186                 return_val_if_nok (error, NULL);
10187                 klass = mono_class_from_mono_type (type);
10188                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10189                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10190                 return_val_if_nok (error, NULL);
10191         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10192                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10193                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10194                 return_val_if_nok (error, NULL);
10195         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10196                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10197                 cinfo = mono_custom_attrs_from_module (module->image, error);
10198                 return_val_if_nok (error, NULL);
10199         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10200                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10201                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10202                 return_val_if_nok (error, NULL);
10203         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10204                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10205                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10206                 return_val_if_nok (error, NULL);
10207         } else if (strcmp ("MonoField", klass->name) == 0) {
10208                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10209                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10210                 return_val_if_nok (error, NULL);
10211         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10212                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10213                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10214                 return_val_if_nok (error, NULL);
10215         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10216                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10217                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10218                 return_val_if_nok (error, NULL);
10219         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10220                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10221                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10222                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10223                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10224                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10225                         return_val_if_nok (error, NULL);
10226                 } else if (is_sr_mono_property (member_class)) {
10227                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10228                         MonoMethod *method;
10229                         if (!(method = prop->property->get))
10230                                 method = prop->property->set;
10231                         g_assert (method);
10232
10233                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10234                         return_val_if_nok (error, NULL);
10235                 } 
10236 #ifndef DISABLE_REFLECTION_EMIT
10237                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10238                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10239                         return_val_if_nok (error, NULL);
10240                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10241                         return_val_if_nok (error, NULL);
10242                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10243                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10244                         MonoMethod *method = NULL;
10245                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10246                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10247                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10248                                 method = ((MonoReflectionMethod *)c->cb)->method;
10249                         else
10250                                 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));
10251
10252                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10253                         return_val_if_nok (error, NULL);
10254                 } 
10255 #endif
10256                 else {
10257                         char *type_name = mono_type_get_full_name (member_class);
10258                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10259                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10260                                                       type_name);
10261                         g_free (type_name);
10262                         return NULL;
10263                 }
10264         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10265                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10266                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10267         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10268                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10269                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10270         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10271                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10272                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10273         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10274                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10275                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10276         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10277                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10278                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10279         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10280                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10281                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10282         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10283                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10284                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10285                 return_val_if_nok (error, NULL);
10286         } else { /* handle other types here... */
10287                 g_error ("get custom attrs not yet supported for %s", klass->name);
10288         }
10289
10290         return cinfo;
10291 }
10292
10293 /*
10294  * mono_reflection_get_custom_attrs_by_type:
10295  * @obj: a reflection object handle
10296  *
10297  * Return an array with all the custom attributes defined of the
10298  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10299  * of that type are returned. The objects are fully build. Return NULL if a loading error
10300  * occurs.
10301  */
10302 MonoArray*
10303 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10304 {
10305         MonoArray *result;
10306         MonoCustomAttrInfo *cinfo;
10307
10308         mono_error_init (error);
10309
10310         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10311         return_val_if_nok (error, NULL);
10312         if (cinfo) {
10313                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10314                 if (!result)
10315                         return NULL;
10316                 if (!cinfo->cached)
10317                         mono_custom_attrs_free (cinfo);
10318         } else {
10319                 mono_loader_assert_no_error ();
10320                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10321         }
10322
10323         return result;
10324 }
10325
10326 /*
10327  * mono_reflection_get_custom_attrs:
10328  * @obj: a reflection object handle
10329  *
10330  * Return an array with all the custom attributes defined of the
10331  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10332  * occurs.
10333  */
10334 MonoArray*
10335 mono_reflection_get_custom_attrs (MonoObject *obj)
10336 {
10337         MonoError error;
10338
10339         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10340 }
10341
10342 /*
10343  * mono_reflection_get_custom_attrs_data:
10344  * @obj: a reflection obj handle
10345  *
10346  * Returns an array of System.Reflection.CustomAttributeData,
10347  * which include information about attributes reflected on
10348  * types loaded using the Reflection Only methods
10349  */
10350 MonoArray*
10351 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10352 {
10353         MonoError error;
10354         MonoArray* result;
10355         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10356         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10357         return result;
10358 }
10359
10360 /*
10361  * mono_reflection_get_custom_attrs_data_checked:
10362  * @obj: a reflection obj handle
10363  * @error: set on error
10364  *
10365  * Returns an array of System.Reflection.CustomAttributeData,
10366  * which include information about attributes reflected on
10367  * types loaded using the Reflection Only methods
10368  */
10369 MonoArray*
10370 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10371 {
10372         MonoArray *result;
10373         MonoCustomAttrInfo *cinfo;
10374
10375         mono_error_init (error);
10376
10377         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10378         return_val_if_nok (error, NULL);
10379         if (cinfo) {
10380                 result = mono_custom_attrs_data_construct (cinfo, error);
10381                 return_val_if_nok (error, NULL);
10382                 if (!cinfo->cached)
10383                         mono_custom_attrs_free (cinfo);
10384         } else
10385                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10386
10387         if (mono_loader_get_last_error ())
10388                 mono_error_set_from_loader_error (error);
10389
10390         return result;
10391 }
10392
10393 static MonoReflectionType*
10394 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10395 {
10396         static MonoMethod *method_get_underlying_system_type = NULL;
10397         MonoReflectionType *rt;
10398         MonoMethod *usertype_method;
10399
10400         mono_error_init (error);
10401
10402         if (!method_get_underlying_system_type)
10403                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10404
10405         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10406
10407         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10408
10409         return rt;
10410 }
10411
10412
10413 static gboolean
10414 is_corlib_type (MonoClass *klass)
10415 {
10416         return klass->image == mono_defaults.corlib;
10417 }
10418
10419 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10420         static MonoClass *cached_class; \
10421         if (cached_class) \
10422                 return cached_class == _class; \
10423         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10424                 cached_class = _class; \
10425                 return TRUE; \
10426         } \
10427         return FALSE; \
10428 } while (0) \
10429
10430
10431 #ifndef DISABLE_REFLECTION_EMIT
10432 static gboolean
10433 is_sre_array (MonoClass *klass)
10434 {
10435         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10436 }
10437
10438 static gboolean
10439 is_sre_byref (MonoClass *klass)
10440 {
10441         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10442 }
10443
10444 static gboolean
10445 is_sre_pointer (MonoClass *klass)
10446 {
10447         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10448 }
10449
10450 static gboolean
10451 is_sre_generic_instance (MonoClass *klass)
10452 {
10453         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10454 }
10455
10456 static gboolean
10457 is_sre_type_builder (MonoClass *klass)
10458 {
10459         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10460 }
10461
10462 static gboolean
10463 is_sre_method_builder (MonoClass *klass)
10464 {
10465         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10466 }
10467
10468 static gboolean
10469 is_sre_ctor_builder (MonoClass *klass)
10470 {
10471         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10472 }
10473
10474 static gboolean
10475 is_sre_field_builder (MonoClass *klass)
10476 {
10477         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10478 }
10479
10480 static gboolean
10481 is_sre_method_on_tb_inst (MonoClass *klass)
10482 {
10483         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10484 }
10485
10486 static gboolean
10487 is_sre_ctor_on_tb_inst (MonoClass *klass)
10488 {
10489         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10490 }
10491
10492 MonoType*
10493 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10494 {
10495         MonoClass *klass;
10496         mono_error_init (error);
10497
10498         if (!ref)
10499                 return NULL;
10500         if (ref->type)
10501                 return ref->type;
10502
10503         if (is_usertype (ref)) {
10504                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10505                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10506                         return NULL;
10507                 if (ref->type)
10508                         return ref->type;
10509         }
10510
10511         klass = mono_object_class (ref);
10512
10513         if (is_sre_array (klass)) {
10514                 MonoType *res;
10515                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10516                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10517                 return_val_if_nok (error, NULL);
10518                 g_assert (base);
10519                 if (sre_array->rank == 0) //single dimentional array
10520                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10521                 else
10522                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10523                 sre_array->type.type = res;
10524                 return res;
10525         } else if (is_sre_byref (klass)) {
10526                 MonoType *res;
10527                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10528                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10529                 return_val_if_nok (error, NULL);
10530                 g_assert (base);
10531                 res = &mono_class_from_mono_type (base)->this_arg;
10532                 sre_byref->type.type = res;
10533                 return res;
10534         } else if (is_sre_pointer (klass)) {
10535                 MonoType *res;
10536                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10537                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10538                 return_val_if_nok (error, NULL);
10539                 g_assert (base);
10540                 res = &mono_ptr_class_get (base)->byval_arg;
10541                 sre_pointer->type.type = res;
10542                 return res;
10543         } else if (is_sre_generic_instance (klass)) {
10544                 MonoType *res, **types;
10545                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10546                 int i, count;
10547
10548                 count = mono_array_length (gclass->type_arguments);
10549                 types = g_new0 (MonoType*, count);
10550                 for (i = 0; i < count; ++i) {
10551                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10552                         types [i] = mono_reflection_type_get_handle (t, error);
10553                         if (!types[i] || !is_ok (error)) {
10554                                 g_free (types);
10555                                 return NULL;
10556                         }
10557                 }
10558
10559                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10560                 g_free (types);
10561                 g_assert (res);
10562                 gclass->type.type = res;
10563                 return res;
10564         }
10565
10566         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10567         return NULL;
10568 }
10569
10570 void
10571 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10572 {
10573         MonoError error;
10574         mono_reflection_type_get_handle (type, &error);
10575         mono_error_set_pending_exception (&error);
10576 }
10577
10578 void
10579 mono_reflection_register_with_runtime (MonoReflectionType *type)
10580 {
10581         MonoError error;
10582         MonoType *res = mono_reflection_type_get_handle (type, &error);
10583         mono_error_raise_exception (&error); /* FIXME don't raise here */
10584         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10585         MonoClass *klass;
10586
10587         if (!res)
10588                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10589
10590         klass = mono_class_from_mono_type (res);
10591
10592         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10593         mono_domain_lock (domain);
10594
10595         if (!image_is_dynamic (klass->image)) {
10596                 mono_class_setup_supertypes (klass);
10597         } else {
10598                 if (!domain->type_hash)
10599                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10600                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10601                 mono_g_hash_table_insert (domain->type_hash, res, type);
10602         }
10603         mono_domain_unlock (domain);
10604         mono_loader_unlock ();
10605 }
10606
10607 /**
10608  * LOCKING: Assumes the loader lock is held.
10609  */
10610 static MonoMethodSignature*
10611 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10612         MonoError error;
10613         MonoMethodSignature *sig;
10614         int count, i;
10615
10616         count = parameters? mono_array_length (parameters): 0;
10617
10618         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10619         sig->param_count = count;
10620         sig->sentinelpos = -1; /* FIXME */
10621         for (i = 0; i < count; ++i) {
10622                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10623                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10624         }
10625         return sig;
10626 }
10627
10628 /**
10629  * LOCKING: Assumes the loader lock is held.
10630  */
10631 static MonoMethodSignature*
10632 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10633         MonoMethodSignature *sig;
10634
10635         sig = parameters_to_signature (image, ctor->parameters);
10636         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10637         sig->ret = &mono_defaults.void_class->byval_arg;
10638         return sig;
10639 }
10640
10641 /**
10642  * LOCKING: Assumes the loader lock is held.
10643  */
10644 static MonoMethodSignature*
10645 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10646         MonoError error;
10647         MonoMethodSignature *sig;
10648
10649         sig = parameters_to_signature (image, method->parameters);
10650         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10651         if (method->rtype) {
10652                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10653                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10654         } else {
10655                 sig->ret = &mono_defaults.void_class->byval_arg;
10656         }
10657         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10658         return sig;
10659 }
10660
10661 static MonoMethodSignature*
10662 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10663         MonoError error;
10664         MonoMethodSignature *sig;
10665
10666         sig = parameters_to_signature (NULL, method->parameters);
10667         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10668         if (method->rtype) {
10669                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10670                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10671         } else {
10672                 sig->ret = &mono_defaults.void_class->byval_arg;
10673         }
10674         sig->generic_param_count = 0;
10675         return sig;
10676 }
10677
10678 static void
10679 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10680 {
10681         MonoError error;
10682         MonoClass *klass = mono_object_class (prop);
10683         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10684                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10685                 *name = mono_string_to_utf8 (pb->name);
10686                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10687                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10688         } else {
10689                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10690                 *name = g_strdup (p->property->name);
10691                 if (p->property->get)
10692                         *type = mono_method_signature (p->property->get)->ret;
10693                 else
10694                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10695         }
10696 }
10697
10698 static void
10699 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10700 {
10701         MonoError error;
10702         MonoClass *klass = mono_object_class (field);
10703         if (strcmp (klass->name, "FieldBuilder") == 0) {
10704                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10705                 *name = mono_string_to_utf8 (fb->name);
10706                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10707                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10708         } else {
10709                 MonoReflectionField *f = (MonoReflectionField *)field;
10710                 *name = g_strdup (mono_field_get_name (f->field));
10711                 *type = f->field->type;
10712         }
10713 }
10714
10715 #else /* DISABLE_REFLECTION_EMIT */
10716
10717 void
10718 mono_reflection_register_with_runtime (MonoReflectionType *type)
10719 {
10720         /* This is empty */
10721 }
10722
10723 static gboolean
10724 is_sre_type_builder (MonoClass *klass)
10725 {
10726         return FALSE;
10727 }
10728
10729 static gboolean
10730 is_sre_generic_instance (MonoClass *klass)
10731 {
10732         return FALSE;
10733 }
10734
10735 static void
10736 init_type_builder_generics (MonoObject *type)
10737 {
10738 }
10739
10740 #endif /* !DISABLE_REFLECTION_EMIT */
10741
10742
10743 static gboolean
10744 is_sr_mono_field (MonoClass *klass)
10745 {
10746         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10747 }
10748
10749 static gboolean
10750 is_sr_mono_property (MonoClass *klass)
10751 {
10752         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10753 }
10754
10755 static gboolean
10756 is_sr_mono_method (MonoClass *klass)
10757 {
10758         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10759 }
10760
10761 static gboolean
10762 is_sr_mono_cmethod (MonoClass *klass)
10763 {
10764         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10765 }
10766
10767 static gboolean
10768 is_sr_mono_generic_method (MonoClass *klass)
10769 {
10770         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10771 }
10772
10773 static gboolean
10774 is_sr_mono_generic_cmethod (MonoClass *klass)
10775 {
10776         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10777 }
10778
10779 gboolean
10780 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10781 {
10782         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10783 }
10784
10785 static gboolean
10786 is_usertype (MonoReflectionType *ref)
10787 {
10788         MonoClass *klass = mono_object_class (ref);
10789         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10790 }
10791
10792 static MonoReflectionType*
10793 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10794 {
10795         mono_error_init (error);
10796         if (!type || type->type)
10797                 return type;
10798
10799         if (is_usertype (type)) {
10800                 type = mono_reflection_type_get_underlying_system_type (type, error);
10801                 return_val_if_nok (error, NULL);
10802                 if (is_usertype (type)) {
10803                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10804                         return NULL;
10805                 }
10806         }
10807
10808         return type;
10809 }
10810 /*
10811  * Encode a value in a custom attribute stream of bytes.
10812  * The value to encode is either supplied as an object in argument val
10813  * (valuetypes are boxed), or as a pointer to the data in the
10814  * argument argval.
10815  * @type represents the type of the value
10816  * @buffer is the start of the buffer
10817  * @p the current position in the buffer
10818  * @buflen contains the size of the buffer and is used to return the new buffer size
10819  * if this needs to be realloced.
10820  * @retbuffer and @retp return the start and the position of the buffer
10821  */
10822 static void
10823 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10824 {
10825         MonoError error;
10826         MonoTypeEnum simple_type;
10827         
10828         if ((p-buffer) + 10 >= *buflen) {
10829                 char *newbuf;
10830                 *buflen *= 2;
10831                 newbuf = (char *)g_realloc (buffer, *buflen);
10832                 p = newbuf + (p-buffer);
10833                 buffer = newbuf;
10834         }
10835         if (!argval)
10836                 argval = ((char*)arg + sizeof (MonoObject));
10837         simple_type = type->type;
10838 handle_enum:
10839         switch (simple_type) {
10840         case MONO_TYPE_BOOLEAN:
10841         case MONO_TYPE_U1:
10842         case MONO_TYPE_I1:
10843                 *p++ = *argval;
10844                 break;
10845         case MONO_TYPE_CHAR:
10846         case MONO_TYPE_U2:
10847         case MONO_TYPE_I2:
10848                 swap_with_size (p, argval, 2, 1);
10849                 p += 2;
10850                 break;
10851         case MONO_TYPE_U4:
10852         case MONO_TYPE_I4:
10853         case MONO_TYPE_R4:
10854                 swap_with_size (p, argval, 4, 1);
10855                 p += 4;
10856                 break;
10857         case MONO_TYPE_R8:
10858                 swap_with_size (p, argval, 8, 1);
10859                 p += 8;
10860                 break;
10861         case MONO_TYPE_U8:
10862         case MONO_TYPE_I8:
10863                 swap_with_size (p, argval, 8, 1);
10864                 p += 8;
10865                 break;
10866         case MONO_TYPE_VALUETYPE:
10867                 if (type->data.klass->enumtype) {
10868                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10869                         goto handle_enum;
10870                 } else {
10871                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10872                 }
10873                 break;
10874         case MONO_TYPE_STRING: {
10875                 char *str;
10876                 guint32 slen;
10877                 if (!arg) {
10878                         *p++ = 0xFF;
10879                         break;
10880                 }
10881                 str = mono_string_to_utf8 ((MonoString*)arg);
10882                 slen = strlen (str);
10883                 if ((p-buffer) + 10 + slen >= *buflen) {
10884                         char *newbuf;
10885                         *buflen *= 2;
10886                         *buflen += slen;
10887                         newbuf = (char *)g_realloc (buffer, *buflen);
10888                         p = newbuf + (p-buffer);
10889                         buffer = newbuf;
10890                 }
10891                 mono_metadata_encode_value (slen, p, &p);
10892                 memcpy (p, str, slen);
10893                 p += slen;
10894                 g_free (str);
10895                 break;
10896         }
10897         case MONO_TYPE_CLASS: {
10898                 char *str;
10899                 guint32 slen;
10900                 MonoType *arg_type;
10901                 if (!arg) {
10902                         *p++ = 0xFF;
10903                         break;
10904                 }
10905 handle_type:
10906                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10907                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10908                 str = type_get_qualified_name (arg_type, NULL);
10909                 slen = strlen (str);
10910                 if ((p-buffer) + 10 + slen >= *buflen) {
10911                         char *newbuf;
10912                         *buflen *= 2;
10913                         *buflen += slen;
10914                         newbuf = (char *)g_realloc (buffer, *buflen);
10915                         p = newbuf + (p-buffer);
10916                         buffer = newbuf;
10917                 }
10918                 mono_metadata_encode_value (slen, p, &p);
10919                 memcpy (p, str, slen);
10920                 p += slen;
10921                 g_free (str);
10922                 break;
10923         }
10924         case MONO_TYPE_SZARRAY: {
10925                 int len, i;
10926                 MonoClass *eclass, *arg_eclass;
10927
10928                 if (!arg) {
10929                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10930                         break;
10931                 }
10932                 len = mono_array_length ((MonoArray*)arg);
10933                 *p++ = len & 0xff;
10934                 *p++ = (len >> 8) & 0xff;
10935                 *p++ = (len >> 16) & 0xff;
10936                 *p++ = (len >> 24) & 0xff;
10937                 *retp = p;
10938                 *retbuffer = buffer;
10939                 eclass = type->data.klass;
10940                 arg_eclass = mono_object_class (arg)->element_class;
10941
10942                 if (!eclass) {
10943                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10944                         eclass = mono_defaults.object_class;
10945                 }
10946                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10947                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10948                         int elsize = mono_class_array_element_size (arg_eclass);
10949                         for (i = 0; i < len; ++i) {
10950                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10951                                 elptr += elsize;
10952                         }
10953                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10954                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10955                         int elsize = mono_class_array_element_size (eclass);
10956                         for (i = 0; i < len; ++i) {
10957                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10958                                 elptr += elsize;
10959                         }
10960                 } else {
10961                         for (i = 0; i < len; ++i) {
10962                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10963                         }
10964                 }
10965                 break;
10966         }
10967         case MONO_TYPE_OBJECT: {
10968                 MonoClass *klass;
10969                 char *str;
10970                 guint32 slen;
10971
10972                 /*
10973                  * The parameter type is 'object' but the type of the actual
10974                  * argument is not. So we have to add type information to the blob
10975                  * too. This is completely undocumented in the spec.
10976                  */
10977
10978                 if (arg == NULL) {
10979                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10980                         *p++ = 0xFF;
10981                         break;
10982                 }
10983                 
10984                 klass = mono_object_class (arg);
10985
10986                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10987                         *p++ = 0x50;
10988                         goto handle_type;
10989                 } else if (klass->enumtype) {
10990                         *p++ = 0x55;
10991                 } else if (klass == mono_defaults.string_class) {
10992                         simple_type = MONO_TYPE_STRING;
10993                         *p++ = 0x0E;
10994                         goto handle_enum;
10995                 } else if (klass->rank == 1) {
10996                         *p++ = 0x1D;
10997                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10998                                 /* See Partition II, Appendix B3 */
10999                                 *p++ = 0x51;
11000                         else
11001                                 *p++ = klass->element_class->byval_arg.type;
11002                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
11003                         break;
11004                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
11005                         *p++ = simple_type = klass->byval_arg.type;
11006                         goto handle_enum;
11007                 } else {
11008                         g_error ("unhandled type in custom attr");
11009                 }
11010                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
11011                 slen = strlen (str);
11012                 if ((p-buffer) + 10 + slen >= *buflen) {
11013                         char *newbuf;
11014                         *buflen *= 2;
11015                         *buflen += slen;
11016                         newbuf = (char *)g_realloc (buffer, *buflen);
11017                         p = newbuf + (p-buffer);
11018                         buffer = newbuf;
11019                 }
11020                 mono_metadata_encode_value (slen, p, &p);
11021                 memcpy (p, str, slen);
11022                 p += slen;
11023                 g_free (str);
11024                 simple_type = mono_class_enum_basetype (klass)->type;
11025                 goto handle_enum;
11026         }
11027         default:
11028                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11029         }
11030         *retp = p;
11031         *retbuffer = buffer;
11032 }
11033
11034 static void
11035 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11036 {
11037         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11038                 char *str = type_get_qualified_name (type, NULL);
11039                 int slen = strlen (str);
11040
11041                 *p++ = 0x55;
11042                 /*
11043                  * This seems to be optional...
11044                  * *p++ = 0x80;
11045                  */
11046                 mono_metadata_encode_value (slen, p, &p);
11047                 memcpy (p, str, slen);
11048                 p += slen;
11049                 g_free (str);
11050         } else if (type->type == MONO_TYPE_OBJECT) {
11051                 *p++ = 0x51;
11052         } else if (type->type == MONO_TYPE_CLASS) {
11053                 /* it should be a type: encode_cattr_value () has the check */
11054                 *p++ = 0x50;
11055         } else {
11056                 mono_metadata_encode_value (type->type, p, &p);
11057                 if (type->type == MONO_TYPE_SZARRAY)
11058                         /* See the examples in Partition VI, Annex B */
11059                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11060         }
11061
11062         *retp = p;
11063 }
11064
11065 #ifndef DISABLE_REFLECTION_EMIT
11066 static void
11067 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11068 {
11069         int len;
11070         /* Preallocate a large enough buffer */
11071         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11072                 char *str = type_get_qualified_name (type, NULL);
11073                 len = strlen (str);
11074                 g_free (str);
11075         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11076                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11077                 len = strlen (str);
11078                 g_free (str);
11079         } else {
11080                 len = 0;
11081         }
11082         len += strlen (name);
11083
11084         if ((p-buffer) + 20 + len >= *buflen) {
11085                 char *newbuf;
11086                 *buflen *= 2;
11087                 *buflen += len;
11088                 newbuf = (char *)g_realloc (buffer, *buflen);
11089                 p = newbuf + (p-buffer);
11090                 buffer = newbuf;
11091         }
11092
11093         encode_field_or_prop_type (type, p, &p);
11094
11095         len = strlen (name);
11096         mono_metadata_encode_value (len, p, &p);
11097         memcpy (p, name, len);
11098         p += len;
11099         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11100         *retp = p;
11101         *retbuffer = buffer;
11102 }
11103
11104 /*
11105  * mono_reflection_get_custom_attrs_blob:
11106  * @ctor: custom attribute constructor
11107  * @ctorArgs: arguments o the constructor
11108  * @properties:
11109  * @propValues:
11110  * @fields:
11111  * @fieldValues:
11112  * 
11113  * Creates the blob of data that needs to be saved in the metadata and that represents
11114  * the custom attributed described by @ctor, @ctorArgs etc.
11115  * Returns: a Byte array representing the blob of data.
11116  */
11117 MonoArray*
11118 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11119 {
11120         MonoArray *result;
11121         MonoMethodSignature *sig;
11122         MonoObject *arg;
11123         char *buffer, *p;
11124         guint32 buflen, i;
11125
11126         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11127                 /* sig is freed later so allocate it in the heap */
11128                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11129         } else {
11130                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11131         }
11132
11133         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11134         buflen = 256;
11135         p = buffer = (char *)g_malloc (buflen);
11136         /* write the prolog */
11137         *p++ = 1;
11138         *p++ = 0;
11139         for (i = 0; i < sig->param_count; ++i) {
11140                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11141                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11142         }
11143         i = 0;
11144         if (properties)
11145                 i += mono_array_length (properties);
11146         if (fields)
11147                 i += mono_array_length (fields);
11148         *p++ = i & 0xff;
11149         *p++ = (i >> 8) & 0xff;
11150         if (properties) {
11151                 MonoObject *prop;
11152                 for (i = 0; i < mono_array_length (properties); ++i) {
11153                         MonoType *ptype;
11154                         char *pname;
11155
11156                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11157                         get_prop_name_and_type (prop, &pname, &ptype);
11158                         *p++ = 0x54; /* PROPERTY signature */
11159                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11160                         g_free (pname);
11161                 }
11162         }
11163
11164         if (fields) {
11165                 MonoObject *field;
11166                 for (i = 0; i < mono_array_length (fields); ++i) {
11167                         MonoType *ftype;
11168                         char *fname;
11169
11170                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11171                         get_field_name_and_type (field, &fname, &ftype);
11172                         *p++ = 0x53; /* FIELD signature */
11173                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11174                         g_free (fname);
11175                 }
11176         }
11177
11178         g_assert (p - buffer <= buflen);
11179         buflen = p - buffer;
11180         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11181         p = mono_array_addr (result, char, 0);
11182         memcpy (p, buffer, buflen);
11183         g_free (buffer);
11184         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11185                 g_free (sig);
11186         return result;
11187 }
11188
11189 /*
11190  * mono_reflection_setup_internal_class:
11191  * @tb: a TypeBuilder object
11192  *
11193  * Creates a MonoClass that represents the TypeBuilder.
11194  * This is a trick that lets us simplify a lot of reflection code
11195  * (and will allow us to support Build and Run assemblies easier).
11196  */
11197 void
11198 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11199 {
11200         MonoError error;
11201         MonoClass *klass, *parent;
11202
11203         RESOLVE_TYPE (tb->parent, &error);
11204         mono_error_raise_exception (&error); /* FIXME don't raise here */
11205
11206         mono_loader_lock ();
11207
11208         if (tb->parent) {
11209                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11210                 if (!is_ok (&error)) {
11211                         mono_loader_unlock ();
11212                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11213                 }
11214                 /* check so we can compile corlib correctly */
11215                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11216                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11217                         parent = parent_type->data.klass;
11218                 } else {
11219                         parent = mono_class_from_mono_type (parent_type);
11220                 }
11221         } else {
11222                 parent = NULL;
11223         }
11224         
11225         /* the type has already being created: it means we just have to change the parent */
11226         if (tb->type.type) {
11227                 klass = mono_class_from_mono_type (tb->type.type);
11228                 klass->parent = NULL;
11229                 /* fool mono_class_setup_parent */
11230                 klass->supertypes = NULL;
11231                 mono_class_setup_parent (klass, parent);
11232                 mono_class_setup_mono_type (klass);
11233                 mono_loader_unlock ();
11234                 return;
11235         }
11236
11237         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11238
11239         klass->image = &tb->module->dynamic_image->image;
11240
11241         klass->inited = 1; /* we lie to the runtime */
11242         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11243         if (!mono_error_ok (&error))
11244                 goto failure;
11245         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11246         if (!mono_error_ok (&error))
11247                 goto failure;
11248         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11249         klass->flags = tb->attrs;
11250         
11251         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11252
11253         klass->element_class = klass;
11254
11255         if (mono_class_get_ref_info (klass) == NULL) {
11256
11257                 mono_class_set_ref_info (klass, tb);
11258
11259                 /* Put into cache so mono_class_get_checked () will find it.
11260                 Skip nested types as those should not be available on the global scope. */
11261                 if (!tb->nesting_type)
11262                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11263
11264                 /*
11265                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11266                 by performing a mono_class_get which does the full resolution.
11267
11268                 Working around this semantics would require us to write a lot of code for no clear advantage.
11269                 */
11270                 mono_image_append_class_to_reflection_info_set (klass);
11271         } else {
11272                 g_assert (mono_class_get_ref_info (klass) == tb);
11273         }
11274
11275         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11276
11277         if (parent != NULL) {
11278                 mono_class_setup_parent (klass, parent);
11279         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11280                 const char *old_n = klass->name;
11281                 /* trick to get relative numbering right when compiling corlib */
11282                 klass->name = "BuildingObject";
11283                 mono_class_setup_parent (klass, mono_defaults.object_class);
11284                 klass->name = old_n;
11285         }
11286
11287         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11288                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11289                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11290                 klass->instance_size = sizeof (MonoObject);
11291                 klass->size_inited = 1;
11292                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11293         }
11294
11295         mono_class_setup_mono_type (klass);
11296
11297         mono_class_setup_supertypes (klass);
11298
11299         /*
11300          * FIXME: handle interfaces.
11301          */
11302
11303         tb->type.type = &klass->byval_arg;
11304
11305         if (tb->nesting_type) {
11306                 g_assert (tb->nesting_type->type);
11307                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11308                 if (!is_ok (&error)) goto failure;
11309                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11310         }
11311
11312         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11313
11314         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11315         
11316         mono_loader_unlock ();
11317         return;
11318
11319 failure:
11320         mono_loader_unlock ();
11321         mono_error_raise_exception (&error);
11322 }
11323
11324 /*
11325  * mono_reflection_setup_generic_class:
11326  * @tb: a TypeBuilder object
11327  *
11328  * Setup the generic class before adding the first generic parameter.
11329  */
11330 void
11331 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11332 {
11333 }
11334
11335 /*
11336  * mono_reflection_create_generic_class:
11337  * @tb: a TypeBuilder object
11338  *
11339  * Creates the generic class after all generic parameters have been added.
11340  */
11341 void
11342 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11343 {
11344         MonoError error;
11345         MonoClass *klass;
11346         int count, i;
11347
11348         klass = mono_class_from_mono_type (tb->type.type);
11349
11350         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11351
11352         if (klass->generic_container || (count == 0))
11353                 return;
11354
11355         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11356
11357         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11358
11359         klass->generic_container->owner.klass = klass;
11360         klass->generic_container->type_argc = count;
11361         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11362
11363         klass->is_generic = 1;
11364
11365         for (i = 0; i < count; i++) {
11366                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11367                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11368                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11369                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11370                 klass->generic_container->type_params [i] = *param;
11371                 /*Make sure we are a diferent type instance */
11372                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11373                 klass->generic_container->type_params [i].info.pklass = NULL;
11374                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11375
11376                 g_assert (klass->generic_container->type_params [i].param.owner);
11377         }
11378
11379         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11380 }
11381
11382 /*
11383  * mono_reflection_create_internal_class:
11384  * @tb: a TypeBuilder object
11385  *
11386  * Actually create the MonoClass that is associated with the TypeBuilder.
11387  */
11388 void
11389 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11390 {
11391         MonoError error;
11392         MonoClass *klass;
11393
11394         klass = mono_class_from_mono_type (tb->type.type);
11395
11396         mono_loader_lock ();
11397         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11398                 MonoReflectionFieldBuilder *fb;
11399                 MonoClass *ec;
11400                 MonoType *enum_basetype;
11401
11402                 g_assert (tb->fields != NULL);
11403                 g_assert (mono_array_length (tb->fields) >= 1);
11404
11405                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11406
11407                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11408                 if (!is_ok (&error)) {
11409                         mono_loader_unlock ();
11410                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11411                 }
11412                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11413                         mono_loader_unlock ();
11414                         return;
11415                 }
11416
11417                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11418                 if (!is_ok (&error)) {
11419                         mono_loader_unlock ();
11420                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11421                 }
11422                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11423                 if (!klass->element_class)
11424                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11425
11426                 /*
11427                  * get the element_class from the current corlib.
11428                  */
11429                 ec = default_class_from_mono_type (enum_basetype);
11430                 klass->instance_size = ec->instance_size;
11431                 klass->size_inited = 1;
11432                 /* 
11433                  * this is almost safe to do with enums and it's needed to be able
11434                  * to create objects of the enum type (for use in SetConstant).
11435                  */
11436                 /* FIXME: Does this mean enums can't have method overrides ? */
11437                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11438         }
11439         mono_loader_unlock ();
11440 }
11441
11442 static MonoMarshalSpec*
11443 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11444                                                                 MonoReflectionMarshal *minfo)
11445 {
11446         MonoError error;
11447         MonoMarshalSpec *res;
11448
11449         res = image_g_new0 (image, MonoMarshalSpec, 1);
11450         res->native = (MonoMarshalNative)minfo->type;
11451
11452         switch (minfo->type) {
11453         case MONO_NATIVE_LPARRAY:
11454                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11455                 if (minfo->has_size) {
11456                         res->data.array_data.param_num = minfo->param_num;
11457                         res->data.array_data.num_elem = minfo->count;
11458                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11459                 }
11460                 else {
11461                         res->data.array_data.param_num = -1;
11462                         res->data.array_data.num_elem = -1;
11463                         res->data.array_data.elem_mult = -1;
11464                 }
11465                 break;
11466
11467         case MONO_NATIVE_BYVALTSTR:
11468         case MONO_NATIVE_BYVALARRAY:
11469                 res->data.array_data.num_elem = minfo->count;
11470                 break;
11471
11472         case MONO_NATIVE_CUSTOM:
11473                 if (minfo->marshaltyperef) {
11474                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11475                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11476                         res->data.custom_data.custom_name =
11477                                 type_get_fully_qualified_name (marshaltyperef);
11478                 }
11479                 if (minfo->mcookie)
11480                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11481                 break;
11482
11483         default:
11484                 break;
11485         }
11486
11487         return res;
11488 }
11489 #endif /* !DISABLE_REFLECTION_EMIT */
11490
11491 MonoReflectionMarshalAsAttribute*
11492 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11493                                                         MonoMarshalSpec *spec, MonoError *error)
11494 {
11495         MonoReflectionType *rt;
11496         MonoReflectionMarshalAsAttribute *minfo;
11497         MonoType *mtype;
11498
11499         mono_error_init (error);
11500         
11501         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11502         if (!minfo)
11503                 return NULL;
11504         minfo->utype = spec->native;
11505
11506         switch (minfo->utype) {
11507         case MONO_NATIVE_LPARRAY:
11508                 minfo->array_subtype = spec->data.array_data.elem_type;
11509                 minfo->size_const = spec->data.array_data.num_elem;
11510                 if (spec->data.array_data.param_num != -1)
11511                         minfo->size_param_index = spec->data.array_data.param_num;
11512                 break;
11513
11514         case MONO_NATIVE_BYVALTSTR:
11515         case MONO_NATIVE_BYVALARRAY:
11516                 minfo->size_const = spec->data.array_data.num_elem;
11517                 break;
11518
11519         case MONO_NATIVE_CUSTOM:
11520                 if (spec->data.custom_data.custom_name) {
11521                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11522                         if (mtype) {
11523                                 rt = mono_type_get_object_checked (domain, mtype, error);
11524                                 if (!rt)
11525                                         return NULL;
11526
11527                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11528                         }
11529
11530                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11531                 }
11532                 if (spec->data.custom_data.cookie)
11533                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11534                 break;
11535
11536         default:
11537                 break;
11538         }
11539
11540         return minfo;
11541 }
11542
11543 #ifndef DISABLE_REFLECTION_EMIT
11544 static MonoMethod*
11545 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11546                                          ReflectionMethodBuilder *rmb,
11547                                          MonoMethodSignature *sig)
11548 {
11549         MonoError error;
11550         MonoMethod *m;
11551         MonoMethodWrapper *wrapperm;
11552         MonoMarshalSpec **specs;
11553         MonoReflectionMethodAux *method_aux;
11554         MonoImage *image;
11555         gboolean dynamic;
11556         int i;
11557
11558         mono_error_init (&error);
11559         /*
11560          * Methods created using a MethodBuilder should have their memory allocated
11561          * inside the image mempool, while dynamic methods should have their memory
11562          * malloc'd.
11563          */
11564         dynamic = rmb->refs != NULL;
11565         image = dynamic ? NULL : klass->image;
11566
11567         if (!dynamic)
11568                 g_assert (!klass->generic_class);
11569
11570         mono_loader_lock ();
11571
11572         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11573                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11574                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11575         else
11576                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11577
11578         wrapperm = (MonoMethodWrapper*)m;
11579
11580         m->dynamic = dynamic;
11581         m->slot = -1;
11582         m->flags = rmb->attrs;
11583         m->iflags = rmb->iattrs;
11584         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11585         m->klass = klass;
11586         m->signature = sig;
11587         m->sre_method = TRUE;
11588         m->skip_visibility = rmb->skip_visibility;
11589         if (rmb->table_idx)
11590                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11591
11592         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11593                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11594                         m->string_ctor = 1;
11595
11596                 m->signature->pinvoke = 1;
11597         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11598                 m->signature->pinvoke = 1;
11599
11600                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11601
11602                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11603                 g_assert (mono_error_ok (&error));
11604                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11605                 g_assert (mono_error_ok (&error));
11606                 
11607                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11608
11609                 if (image_is_dynamic (klass->image))
11610                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11611
11612                 mono_loader_unlock ();
11613
11614                 return m;
11615         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11616                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11617                 MonoMethodHeader *header;
11618                 guint32 code_size;
11619                 gint32 max_stack, i;
11620                 gint32 num_locals = 0;
11621                 gint32 num_clauses = 0;
11622                 guint8 *code;
11623
11624                 if (rmb->ilgen) {
11625                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11626                         code_size = rmb->ilgen->code_len;
11627                         max_stack = rmb->ilgen->max_stack;
11628                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11629                         if (rmb->ilgen->ex_handlers)
11630                                 num_clauses = method_count_clauses (rmb->ilgen);
11631                 } else {
11632                         if (rmb->code) {
11633                                 code = mono_array_addr (rmb->code, guint8, 0);
11634                                 code_size = mono_array_length (rmb->code);
11635                                 /* we probably need to run a verifier on the code... */
11636                                 max_stack = 8; 
11637                         }
11638                         else {
11639                                 code = NULL;
11640                                 code_size = 0;
11641                                 max_stack = 8;
11642                         }
11643                 }
11644
11645                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11646                 header->code_size = code_size;
11647                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11648                 memcpy ((char*)header->code, code, code_size);
11649                 header->max_stack = max_stack;
11650                 header->init_locals = rmb->init_locals;
11651                 header->num_locals = num_locals;
11652
11653                 for (i = 0; i < num_locals; ++i) {
11654                         MonoReflectionLocalBuilder *lb = 
11655                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11656
11657                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11658                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11659                         mono_error_assert_ok (&error);
11660                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11661                 }
11662
11663                 header->num_clauses = num_clauses;
11664                 if (num_clauses) {
11665                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11666                                                                  rmb->ilgen, num_clauses, &error);
11667                         mono_error_assert_ok (&error);
11668                 }
11669
11670                 wrapperm->header = header;
11671         }
11672
11673         if (rmb->generic_params) {
11674                 int count = mono_array_length (rmb->generic_params);
11675                 MonoGenericContainer *container = rmb->generic_container;
11676
11677                 g_assert (container);
11678
11679                 container->type_argc = count;
11680                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11681                 container->owner.method = m;
11682                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11683
11684                 m->is_generic = TRUE;
11685                 mono_method_set_generic_container (m, container);
11686
11687                 for (i = 0; i < count; i++) {
11688                         MonoReflectionGenericParam *gp =
11689                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11690                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11691                         mono_error_assert_ok (&error);
11692                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11693                         container->type_params [i] = *param;
11694                 }
11695
11696                 /*
11697                  * The method signature might have pointers to generic parameters that belong to other methods.
11698                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11699                  * generic parameters.
11700                  */
11701                 for (i = 0; i < m->signature->param_count; ++i) {
11702                         MonoType *t = m->signature->params [i];
11703                         if (t->type == MONO_TYPE_MVAR) {
11704                                 MonoGenericParam *gparam =  t->data.generic_param;
11705                                 if (gparam->num < count) {
11706                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11707                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11708                                 }
11709
11710                         }
11711                 }
11712
11713                 if (klass->generic_container) {
11714                         container->parent = klass->generic_container;
11715                         container->context.class_inst = klass->generic_container->context.class_inst;
11716                 }
11717                 container->context.method_inst = mono_get_shared_generic_inst (container);
11718         }
11719
11720         if (rmb->refs) {
11721                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11722                 int i;
11723                 void **data;
11724
11725                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11726
11727                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11728                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11729                 for (i = 0; i < rmb->nrefs; ++i)
11730                         data [i + 1] = rmb->refs [i];
11731         }
11732
11733         method_aux = NULL;
11734
11735         /* Parameter info */
11736         if (rmb->pinfo) {
11737                 if (!method_aux)
11738                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11739                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11740                 for (i = 0; i <= m->signature->param_count; ++i) {
11741                         MonoReflectionParamBuilder *pb;
11742                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11743                                 if ((i > 0) && (pb->attrs)) {
11744                                         /* Make a copy since it might point to a shared type structure */
11745                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11746                                         m->signature->params [i - 1]->attrs = pb->attrs;
11747                                 }
11748
11749                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11750                                         MonoDynamicImage *assembly;
11751                                         guint32 idx, len;
11752                                         MonoTypeEnum def_type;
11753                                         char *p;
11754                                         const char *p2;
11755
11756                                         if (!method_aux->param_defaults) {
11757                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11758                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11759                                         }
11760                                         assembly = (MonoDynamicImage*)klass->image;
11761                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11762                                         /* Copy the data from the blob since it might get realloc-ed */
11763                                         p = assembly->blob.data + idx;
11764                                         len = mono_metadata_decode_blob_size (p, &p2);
11765                                         len += p2 - p;
11766                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11767                                         method_aux->param_default_types [i] = def_type;
11768                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11769                                 }
11770
11771                                 if (pb->name) {
11772                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11773                                         g_assert (mono_error_ok (&error));
11774                                 }
11775                                 if (pb->cattrs) {
11776                                         if (!method_aux->param_cattr)
11777                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11778                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11779                                 }
11780                         }
11781                 }
11782         }
11783
11784         /* Parameter marshalling */
11785         specs = NULL;
11786         if (rmb->pinfo)         
11787                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11788                         MonoReflectionParamBuilder *pb;
11789                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11790                                 if (pb->marshal_info) {
11791                                         if (specs == NULL)
11792                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11793                                         specs [pb->position] = 
11794                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11795                                 }
11796                         }
11797                 }
11798         if (specs != NULL) {
11799                 if (!method_aux)
11800                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11801                 method_aux->param_marshall = specs;
11802         }
11803
11804         if (image_is_dynamic (klass->image) && method_aux)
11805                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11806
11807         mono_loader_unlock ();
11808
11809         return m;
11810 }       
11811
11812 static MonoMethod*
11813 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11814 {
11815         ReflectionMethodBuilder rmb;
11816         MonoMethodSignature *sig;
11817
11818         mono_loader_lock ();
11819         sig = ctor_builder_to_signature (klass->image, mb);
11820         mono_loader_unlock ();
11821
11822         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11823                 return NULL;
11824
11825         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11826         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11827
11828         /* If we are in a generic class, we might be called multiple times from inflate_method */
11829         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11830                 /* ilgen is no longer needed */
11831                 mb->ilgen = NULL;
11832         }
11833
11834         return mb->mhandle;
11835 }
11836
11837 static MonoMethod*
11838 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11839 {
11840         ReflectionMethodBuilder rmb;
11841         MonoMethodSignature *sig;
11842
11843         mono_error_init (error);
11844
11845         mono_loader_lock ();
11846         sig = method_builder_to_signature (klass->image, mb);
11847         mono_loader_unlock ();
11848
11849         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11850                 return NULL;
11851
11852         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11853         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11854
11855         /* If we are in a generic class, we might be called multiple times from inflate_method */
11856         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11857                 /* ilgen is no longer needed */
11858                 mb->ilgen = NULL;
11859         }
11860         return mb->mhandle;
11861 }
11862
11863 static MonoClassField*
11864 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11865 {
11866         MonoClassField *field;
11867         MonoType *custom;
11868         MonoError error;
11869
11870         field = g_new0 (MonoClassField, 1);
11871
11872         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11873         g_assert (mono_error_ok (&error));
11874         if (fb->attrs || fb->modreq || fb->modopt) {
11875                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11876                 if (!is_ok (&error)) {
11877                         g_free (field);
11878                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11879                 }
11880                 field->type = mono_metadata_type_dup (NULL, type);
11881                 field->type->attrs = fb->attrs;
11882
11883                 g_assert (image_is_dynamic (klass->image));
11884                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
11885                 g_free (field->type);
11886                 if (!is_ok (&error)) {
11887                         g_free (field);
11888                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11889                 }
11890                 field->type = mono_metadata_type_dup (klass->image, custom);
11891                 g_free (custom);
11892         } else {
11893                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11894                 if (!is_ok (&error)) {
11895                         g_free (field);
11896                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11897                 }
11898         }
11899         if (fb->offset != -1)
11900                 field->offset = fb->offset;
11901         field->parent = klass;
11902         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11903
11904         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11905
11906         return field;
11907 }
11908 #endif
11909
11910 MonoType*
11911 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11912 {
11913         MonoError error;
11914         MonoClass *klass;
11915         MonoReflectionTypeBuilder *tb = NULL;
11916         gboolean is_dynamic = FALSE;
11917         MonoClass *geninst;
11918
11919         mono_loader_lock ();
11920
11921         if (is_sre_type_builder (mono_object_class (type))) {
11922                 tb = (MonoReflectionTypeBuilder *) type;
11923
11924                 is_dynamic = TRUE;
11925         } else if (is_sre_generic_instance (mono_object_class (type))) {
11926                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11927                 MonoReflectionType *gtd = rgi->generic_type;
11928
11929                 if (is_sre_type_builder (mono_object_class (gtd))) {
11930                         tb = (MonoReflectionTypeBuilder *)gtd;
11931                         is_dynamic = TRUE;
11932                 }
11933         }
11934
11935         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11936         if (tb && tb->generic_container)
11937                 mono_reflection_create_generic_class (tb);
11938
11939         MonoType *t = mono_reflection_type_get_handle (type, &error);
11940         mono_error_raise_exception (&error); /* FIXME don't raise here */
11941
11942         klass = mono_class_from_mono_type (t);
11943         if (!klass->generic_container) {
11944                 mono_loader_unlock ();
11945                 return NULL;
11946         }
11947
11948         if (klass->wastypebuilder) {
11949                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11950
11951                 is_dynamic = TRUE;
11952         }
11953
11954         mono_loader_unlock ();
11955
11956         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11957
11958         return &geninst->byval_arg;
11959 }
11960
11961 MonoClass*
11962 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11963 {
11964         MonoGenericClass *gclass;
11965         MonoGenericInst *inst;
11966
11967         g_assert (klass->generic_container);
11968
11969         inst = mono_metadata_get_generic_inst (type_argc, types);
11970         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11971
11972         return mono_generic_class_get_class (gclass);
11973 }
11974
11975 MonoReflectionMethod*
11976 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11977 {
11978         MonoError error;
11979         MonoClass *klass;
11980         MonoMethod *method, *inflated;
11981         MonoMethodInflated *imethod;
11982         MonoGenericContext tmp_context;
11983         MonoGenericInst *ginst;
11984         MonoType **type_argv;
11985         int count, i;
11986
11987         /*FIXME but this no longer should happen*/
11988         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11989 #ifndef DISABLE_REFLECTION_EMIT
11990                 MonoReflectionMethodBuilder *mb = NULL;
11991                 MonoType *tb;
11992                 MonoClass *klass;
11993
11994                 mb = (MonoReflectionMethodBuilder *) rmethod;
11995                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11996                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11997                 klass = mono_class_from_mono_type (tb);
11998
11999                 method = methodbuilder_to_mono_method (klass, mb, &error);
12000                 if (!method)
12001                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12002 #else
12003                 g_assert_not_reached ();
12004                 method = NULL;
12005 #endif
12006         } else {
12007                 method = rmethod->method;
12008         }
12009
12010         klass = method->klass;
12011
12012         if (method->is_inflated)
12013                 method = ((MonoMethodInflated *) method)->declaring;
12014
12015         count = mono_method_signature (method)->generic_param_count;
12016         if (count != mono_array_length (types))
12017                 return NULL;
12018
12019         type_argv = g_new0 (MonoType *, count);
12020         for (i = 0; i < count; i++) {
12021                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12022                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12023                 if (!is_ok (&error)) {
12024                         g_free (type_argv);
12025                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12026                 }
12027         }
12028         ginst = mono_metadata_get_generic_inst (count, type_argv);
12029         g_free (type_argv);
12030
12031         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12032         tmp_context.method_inst = ginst;
12033
12034         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12035         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12036         imethod = (MonoMethodInflated *) inflated;
12037
12038         /*FIXME but I think this is no longer necessary*/
12039         if (image_is_dynamic (method->klass->image)) {
12040                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12041                 /*
12042                  * This table maps metadata structures representing inflated methods/fields
12043                  * to the reflection objects representing their generic definitions.
12044                  */
12045                 mono_image_lock ((MonoImage*)image);
12046                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12047                 mono_image_unlock ((MonoImage*)image);
12048         }
12049
12050         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12051                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12052         
12053         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12054         mono_error_raise_exception (&error); /* FIXME don't raise here */
12055         return ret;
12056 }
12057
12058 #ifndef DISABLE_REFLECTION_EMIT
12059
12060 static MonoMethod *
12061 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12062 {
12063         MonoMethodInflated *imethod;
12064         MonoGenericContext *context;
12065         int i;
12066
12067         /*
12068          * With generic code sharing the klass might not be inflated.
12069          * This can happen because classes inflated with their own
12070          * type arguments are "normalized" to the uninflated class.
12071          */
12072         if (!klass->generic_class)
12073                 return method;
12074
12075         context = mono_class_get_context (klass);
12076
12077         if (klass->method.count && klass->methods) {
12078                 /* Find the already created inflated method */
12079                 for (i = 0; i < klass->method.count; ++i) {
12080                         g_assert (klass->methods [i]->is_inflated);
12081                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12082                                 break;
12083                 }
12084                 g_assert (i < klass->method.count);
12085                 imethod = (MonoMethodInflated*)klass->methods [i];
12086         } else {
12087                 MonoError error;
12088                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12089                 mono_error_assert_ok (&error);
12090         }
12091
12092         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12093                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12094
12095                 mono_image_lock ((MonoImage*)image);
12096                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12097                 mono_image_unlock ((MonoImage*)image);
12098         }
12099         return (MonoMethod *) imethod;
12100 }
12101
12102 static MonoMethod *
12103 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12104 {
12105         MonoMethod *method;
12106         MonoClass *gklass;
12107
12108         mono_error_init (error);
12109
12110         MonoClass *type_class = mono_object_class (type);
12111
12112         if (is_sre_generic_instance (type_class)) {
12113                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12114                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12115                 return_val_if_nok (error, NULL);
12116                 gklass = mono_class_from_mono_type (generic_type);
12117         } else if (is_sre_type_builder (type_class)) {
12118                 MonoType *t = mono_reflection_type_get_handle (type, error);
12119                 return_val_if_nok (error, NULL);
12120                 gklass = mono_class_from_mono_type (t);
12121         } else if (type->type) {
12122                 gklass = mono_class_from_mono_type (type->type);
12123                 gklass = mono_class_get_generic_type_definition (gklass);
12124         } else {
12125                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12126         }
12127
12128         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12129                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12130                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12131                 else {
12132                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12133                         if (!method)
12134                                 return NULL;
12135                 }
12136         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12137                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12138                 if (!method)
12139                         return NULL;
12140         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12141                 method = ((MonoReflectionMethod *) obj)->method;
12142         else {
12143                 method = NULL; /* prevent compiler warning */
12144                 g_error ("can't handle type %s", obj->vtable->klass->name);
12145         }
12146
12147         MonoType *t = mono_reflection_type_get_handle (type, error);
12148         return_val_if_nok (error, NULL);
12149         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12150 }
12151
12152 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12153 void
12154 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12155 {
12156         MonoError error;
12157         MonoGenericClass *gclass;
12158         MonoDynamicGenericClass *dgclass;
12159         MonoClass *klass, *gklass;
12160         MonoType *gtype;
12161         int i;
12162
12163         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12164         mono_error_raise_exception (&error); /* FIXME don't raise here */
12165         klass = mono_class_from_mono_type (gtype);
12166         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12167         gclass = gtype->data.generic_class;
12168
12169         if (!gclass->is_dynamic)
12170                 return;
12171
12172         dgclass = (MonoDynamicGenericClass *) gclass;
12173
12174         if (dgclass->initialized)
12175                 return;
12176
12177         gklass = gclass->container_class;
12178         mono_class_init (gklass);
12179
12180         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12181
12182         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12183         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12184         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12185
12186         for (i = 0; i < dgclass->count_fields; i++) {
12187                 MonoError error;
12188                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12189                 MonoClassField *field, *inflated_field = NULL;
12190
12191                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12192                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12193                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12194                         field = ((MonoReflectionField *) obj)->field;
12195                 else {
12196                         field = NULL; /* prevent compiler warning */
12197                         g_assert_not_reached ();
12198                 }
12199
12200                 dgclass->fields [i] = *field;
12201                 dgclass->fields [i].parent = klass;
12202                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12203                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12204                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12205                 dgclass->field_generic_types [i] = field->type;
12206                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12207                 dgclass->field_objects [i] = obj;
12208
12209                 if (inflated_field) {
12210                         g_free (inflated_field);
12211                 } else {
12212                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12213                 }
12214         }
12215
12216         dgclass->initialized = TRUE;
12217 }
12218
12219 void
12220 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12221 {
12222         MonoDynamicGenericClass *dgclass;
12223         int i;
12224
12225         g_assert (gclass->is_dynamic);
12226
12227         dgclass = (MonoDynamicGenericClass *)gclass;
12228
12229         for (i = 0; i < dgclass->count_fields; ++i) {
12230                 MonoClassField *field = dgclass->fields + i;
12231                 mono_metadata_free_type (field->type);
12232                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12233         }
12234 }
12235
12236 static void
12237 fix_partial_generic_class (MonoClass *klass)
12238 {
12239         MonoClass *gklass = klass->generic_class->container_class;
12240         MonoDynamicGenericClass *dgclass;
12241         int i;
12242
12243         if (klass->wastypebuilder)
12244                 return;
12245
12246         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12247         if (klass->parent != gklass->parent) {
12248                 MonoError error;
12249                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12250                 if (mono_error_ok (&error)) {
12251                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12252                         mono_metadata_free_type (parent_type);
12253                         if (parent != klass->parent) {
12254                                 /*fool mono_class_setup_parent*/
12255                                 klass->supertypes = NULL;
12256                                 mono_class_setup_parent (klass, parent);
12257                         }
12258                 } else {
12259                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12260                         mono_error_cleanup (&error);
12261                         if (gklass->wastypebuilder)
12262                                 klass->wastypebuilder = TRUE;
12263                         return;
12264                 }
12265         }
12266
12267         if (!dgclass->initialized)
12268                 return;
12269
12270         if (klass->method.count != gklass->method.count) {
12271                 klass->method.count = gklass->method.count;
12272                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12273
12274                 for (i = 0; i < klass->method.count; i++) {
12275                         MonoError error;
12276                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12277                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12278                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12279                 }
12280         }
12281
12282         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12283                 klass->interface_count = gklass->interface_count;
12284                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12285                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12286
12287                 for (i = 0; i < gklass->interface_count; ++i) {
12288                         MonoError error;
12289                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12290                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12291
12292                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12293                         mono_metadata_free_type (iface_type);
12294
12295                         ensure_runtime_vtable (klass->interfaces [i], &error);
12296                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12297                 }
12298                 klass->interfaces_inited = 1;
12299         }
12300
12301         if (klass->field.count != gklass->field.count) {
12302                 klass->field.count = gklass->field.count;
12303                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12304
12305                 for (i = 0; i < klass->field.count; i++) {
12306                         MonoError error;
12307                         klass->fields [i] = gklass->fields [i];
12308                         klass->fields [i].parent = klass;
12309                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12310                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12311                 }
12312         }
12313
12314         /*We can only finish with this klass once it's parent has as well*/
12315         if (gklass->wastypebuilder)
12316                 klass->wastypebuilder = TRUE;
12317         return;
12318 }
12319
12320 /**
12321  * ensure_generic_class_runtime_vtable:
12322  * @klass a generic class
12323  * @error set on error
12324  *
12325  * Ensures that the generic container of @klass has a vtable and
12326  * returns TRUE on success.  On error returns FALSE and sets @error.
12327  */
12328 static gboolean
12329 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12330 {
12331         MonoClass *gklass = klass->generic_class->container_class;
12332
12333         mono_error_init (error);
12334
12335         if (!ensure_runtime_vtable (gklass, error))
12336                 return FALSE;
12337
12338         fix_partial_generic_class (klass);
12339
12340         return TRUE;
12341 }
12342
12343 /**
12344  * ensure_runtime_vtable:
12345  * @klass the class
12346  * @error set on error
12347  *
12348  * Ensures that @klass has a vtable and returns TRUE on success. On
12349  * error returns FALSE and sets @error.
12350  */
12351 static gboolean
12352 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12353 {
12354         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12355         int i, num, j;
12356
12357         mono_error_init (error);
12358
12359         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12360                 return TRUE;
12361         if (klass->parent)
12362                 if (!ensure_runtime_vtable (klass->parent, error))
12363                         return FALSE;
12364
12365         if (tb) {
12366                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12367                 num += tb->num_methods;
12368                 klass->method.count = num;
12369                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12370                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12371                 for (i = 0; i < num; ++i) {
12372                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12373                         if (!ctor)
12374                                 return FALSE;
12375                         klass->methods [i] = ctor;
12376                 }
12377                 num = tb->num_methods;
12378                 j = i;
12379                 for (i = 0; i < num; ++i) {
12380                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12381                         if (!meth)
12382                                 return FALSE;
12383                         klass->methods [j++] = meth;
12384                 }
12385         
12386                 if (tb->interfaces) {
12387                         klass->interface_count = mono_array_length (tb->interfaces);
12388                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12389                         for (i = 0; i < klass->interface_count; ++i) {
12390                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12391                                 return_val_if_nok (error, FALSE);
12392                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12393                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12394                                         return FALSE;
12395                         }
12396                         klass->interfaces_inited = 1;
12397                 }
12398         } else if (klass->generic_class){
12399                 if (!ensure_generic_class_runtime_vtable (klass, error))
12400                         return FALSE;
12401         }
12402
12403         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12404                 int slot_num = 0;
12405                 for (i = 0; i < klass->method.count; ++i) {
12406                         MonoMethod *im = klass->methods [i];
12407                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12408                                 im->slot = slot_num++;
12409                 }
12410                 
12411                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12412                 mono_class_setup_interface_offsets (klass);
12413                 mono_class_setup_interface_id (klass);
12414         }
12415
12416         /*
12417          * The generic vtable is needed even if image->run is not set since some
12418          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12419          * method->slot being defined.
12420          */
12421
12422         /* 
12423          * tb->methods could not be freed since it is used for determining 
12424          * overrides during dynamic vtable construction.
12425          */
12426
12427         return TRUE;
12428 }
12429
12430 static MonoMethod*
12431 mono_reflection_method_get_handle (MonoObject *method)
12432 {
12433         MonoError error;
12434         MonoClass *klass = mono_object_class (method);
12435         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12436                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12437                 return sr_method->method;
12438         }
12439         if (is_sre_method_builder (klass)) {
12440                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12441                 return mb->mhandle;
12442         }
12443         if (is_sre_method_on_tb_inst (klass)) {
12444                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12445                 MonoMethod *result;
12446                 /*FIXME move this to a proper method and unify with resolve_object*/
12447                 if (m->method_args) {
12448                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12449                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12450                 } else {
12451                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12452                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12453                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12454                         MonoMethod *mono_method;
12455
12456                         if (is_sre_method_builder (mono_object_class (m->mb)))
12457                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12458                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12459                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12460                         else
12461                                 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)));
12462
12463                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12464                 }
12465                 return result;
12466         }
12467
12468         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12469         return NULL;
12470 }
12471
12472 void
12473 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12474 {
12475         MonoReflectionTypeBuilder *tb;
12476         int i, j, onum;
12477         MonoReflectionMethod *m;
12478
12479         *overrides = NULL;
12480         *num_overrides = 0;
12481
12482         g_assert (image_is_dynamic (klass->image));
12483
12484         if (!mono_class_get_ref_info (klass))
12485                 return;
12486
12487         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12488
12489         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12490
12491         onum = 0;
12492         if (tb->methods) {
12493                 for (i = 0; i < tb->num_methods; ++i) {
12494                         MonoReflectionMethodBuilder *mb = 
12495                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12496                         if (mb->override_methods)
12497                                 onum += mono_array_length (mb->override_methods);
12498                 }
12499         }
12500
12501         if (onum) {
12502                 *overrides = g_new0 (MonoMethod*, onum * 2);
12503
12504                 onum = 0;
12505                 for (i = 0; i < tb->num_methods; ++i) {
12506                         MonoReflectionMethodBuilder *mb = 
12507                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12508                         if (mb->override_methods) {
12509                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12510                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12511
12512                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12513                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12514
12515                                         g_assert (mb->mhandle);
12516
12517                                         onum ++;
12518                                 }
12519                         }
12520                 }
12521         }
12522
12523         *num_overrides = onum;
12524 }
12525
12526 static void
12527 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12528 {
12529         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12530         MonoReflectionFieldBuilder *fb;
12531         MonoClassField *field;
12532         MonoImage *image = klass->image;
12533         const char *p, *p2;
12534         int i;
12535         guint32 len, idx, real_size = 0;
12536
12537         klass->field.count = tb->num_fields;
12538         klass->field.first = 0;
12539
12540         mono_error_init (error);
12541
12542         if (tb->class_size) {
12543                 if ((tb->packing_size & 0xffffff00) != 0) {
12544                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12545                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12546                         return;
12547                 }
12548                 klass->packing_size = tb->packing_size;
12549                 real_size = klass->instance_size + tb->class_size;
12550         }
12551
12552         if (!klass->field.count) {
12553                 klass->instance_size = MAX (klass->instance_size, real_size);
12554                 return;
12555         }
12556         
12557         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12558         mono_class_alloc_ext (klass);
12559         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12560         /*
12561         This is, guess what, a hack.
12562         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12563         On the static path no field class is resolved, only types are built. This is the right thing to do
12564         but we suck.
12565         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12566         */
12567         klass->size_inited = 1;
12568
12569         for (i = 0; i < klass->field.count; ++i) {
12570                 MonoArray *rva_data;
12571                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12572                 field = &klass->fields [i];
12573                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12574                 if (!mono_error_ok (error))
12575                         return;
12576                 if (fb->attrs) {
12577                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12578                         return_if_nok (error);
12579                         field->type = mono_metadata_type_dup (klass->image, type);
12580                         field->type->attrs = fb->attrs;
12581                 } else {
12582                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12583                         return_if_nok (error);
12584                 }
12585
12586                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12587                         char *base = mono_array_addr (rva_data, char, 0);
12588                         size_t size = mono_array_length (rva_data);
12589                         char *data = (char *)mono_image_alloc (klass->image, size);
12590                         memcpy (data, base, size);
12591                         klass->ext->field_def_values [i].data = data;
12592                 }
12593                 if (fb->offset != -1)
12594                         field->offset = fb->offset;
12595                 field->parent = klass;
12596                 fb->handle = field;
12597                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12598
12599                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12600                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12601                 }
12602                 if (fb->def_value) {
12603                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12604                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12605                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12606                         /* Copy the data from the blob since it might get realloc-ed */
12607                         p = assembly->blob.data + idx;
12608                         len = mono_metadata_decode_blob_size (p, &p2);
12609                         len += p2 - p;
12610                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12611                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12612                 }
12613         }
12614
12615         klass->instance_size = MAX (klass->instance_size, real_size);
12616         mono_class_layout_fields (klass);
12617 }
12618
12619 static void
12620 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12621 {
12622         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12623         MonoReflectionPropertyBuilder *pb;
12624         MonoImage *image = klass->image;
12625         MonoProperty *properties;
12626         int i;
12627
12628         mono_error_init (error);
12629
12630         if (!klass->ext)
12631                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12632
12633         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12634         klass->ext->property.first = 0;
12635
12636         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12637         klass->ext->properties = properties;
12638         for (i = 0; i < klass->ext->property.count; ++i) {
12639                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12640                 properties [i].parent = klass;
12641                 properties [i].attrs = pb->attrs;
12642                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12643                 if (!mono_error_ok (error))
12644                         return;
12645                 if (pb->get_method)
12646                         properties [i].get = pb->get_method->mhandle;
12647                 if (pb->set_method)
12648                         properties [i].set = pb->set_method->mhandle;
12649
12650                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12651                 if (pb->def_value) {
12652                         guint32 len, idx;
12653                         const char *p, *p2;
12654                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12655                         if (!klass->ext->prop_def_values)
12656                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12657                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12658                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12659                         /* Copy the data from the blob since it might get realloc-ed */
12660                         p = assembly->blob.data + idx;
12661                         len = mono_metadata_decode_blob_size (p, &p2);
12662                         len += p2 - p;
12663                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12664                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12665                 }
12666         }
12667 }
12668
12669 MonoReflectionEvent *
12670 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12671 {
12672         MonoError error;
12673         MonoEvent *event = g_new0 (MonoEvent, 1);
12674         MonoClass *klass;
12675
12676         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12677         mono_error_raise_exception (&error); /* FIXME don't raise here */
12678         klass = mono_class_from_mono_type (type);
12679
12680         event->parent = klass;
12681         event->attrs = eb->attrs;
12682         event->name = mono_string_to_utf8 (eb->name);
12683         if (eb->add_method)
12684                 event->add = eb->add_method->mhandle;
12685         if (eb->remove_method)
12686                 event->remove = eb->remove_method->mhandle;
12687         if (eb->raise_method)
12688                 event->raise = eb->raise_method->mhandle;
12689
12690 #ifndef MONO_SMALL_CONFIG
12691         if (eb->other_methods) {
12692                 int j;
12693                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12694                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12695                         MonoReflectionMethodBuilder *mb = 
12696                                 mono_array_get (eb->other_methods,
12697                                                 MonoReflectionMethodBuilder*, j);
12698                         event->other [j] = mb->mhandle;
12699                 }
12700         }
12701 #endif
12702
12703         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12704         mono_error_raise_exception (&error); /* FIXME don't raise here */
12705         return ev_obj;
12706 }
12707
12708 static void
12709 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12710 {
12711         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12712         MonoReflectionEventBuilder *eb;
12713         MonoImage *image = klass->image;
12714         MonoEvent *events;
12715         int i;
12716
12717         mono_error_init (error);
12718
12719         if (!klass->ext)
12720                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12721
12722         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12723         klass->ext->event.first = 0;
12724
12725         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12726         klass->ext->events = events;
12727         for (i = 0; i < klass->ext->event.count; ++i) {
12728                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12729                 events [i].parent = klass;
12730                 events [i].attrs = eb->attrs;
12731                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12732                 if (!mono_error_ok (error))
12733                         return;
12734                 if (eb->add_method)
12735                         events [i].add = eb->add_method->mhandle;
12736                 if (eb->remove_method)
12737                         events [i].remove = eb->remove_method->mhandle;
12738                 if (eb->raise_method)
12739                         events [i].raise = eb->raise_method->mhandle;
12740
12741 #ifndef MONO_SMALL_CONFIG
12742                 if (eb->other_methods) {
12743                         int j;
12744                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12745                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12746                                 MonoReflectionMethodBuilder *mb = 
12747                                         mono_array_get (eb->other_methods,
12748                                                                         MonoReflectionMethodBuilder*, j);
12749                                 events [i].other [j] = mb->mhandle;
12750                         }
12751                 }
12752 #endif
12753                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12754         }
12755 }
12756
12757 static gboolean
12758 remove_instantiations_of_and_ensure_contents (gpointer key,
12759                                                   gpointer value,
12760                                                   gpointer user_data)
12761 {
12762         MonoType *type = (MonoType*)key;
12763         MonoClass *klass = (MonoClass*)user_data;
12764
12765         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12766                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12767                 return TRUE;
12768         } else
12769                 return FALSE;
12770 }
12771
12772 static void
12773 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12774 {
12775         mono_error_init (error);
12776         int i;
12777
12778         if (!arr)
12779                 return;
12780
12781         for (i = 0; i < mono_array_length (arr); ++i) {
12782                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12783                 if (!mono_error_ok (error))
12784                         break;
12785         }
12786 }
12787
12788 MonoReflectionType*
12789 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12790 {
12791         MonoError error;
12792         MonoClass *klass;
12793         MonoDomain* domain;
12794         MonoReflectionType* res;
12795         int i, j;
12796
12797         domain = mono_object_domain (tb);
12798         klass = mono_class_from_mono_type (tb->type.type);
12799
12800         /*
12801          * Check for user defined Type subclasses.
12802          */
12803         RESOLVE_TYPE (tb->parent, &error);
12804         mono_error_raise_exception (&error); /* FIXME don't raise here */
12805         check_array_for_usertypes (tb->interfaces, &error);
12806         mono_error_raise_exception (&error); /*FIXME don't raise here */
12807         if (tb->fields) {
12808                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12809                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12810                         if (fb) {
12811                                 RESOLVE_TYPE (fb->type, &error);
12812                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12813                                 check_array_for_usertypes (fb->modreq, &error);
12814                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12815                                 check_array_for_usertypes (fb->modopt, &error);
12816                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12817                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12818                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12819                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12820                                 }
12821                         }
12822                 }
12823         }
12824         if (tb->methods) {
12825                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12826                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12827                         if (mb) {
12828                                 RESOLVE_TYPE (mb->rtype, &error);
12829                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12830                                 check_array_for_usertypes (mb->return_modreq, &error);
12831                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12832                                 check_array_for_usertypes (mb->return_modopt, &error);
12833                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12834                                 check_array_for_usertypes (mb->parameters, &error);
12835                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12836                                 if (mb->param_modreq)
12837                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12838                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12839                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12840                                         }
12841                                 if (mb->param_modopt)
12842                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12843                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12844                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12845                                         }
12846                         }
12847                 }
12848         }
12849         if (tb->ctors) {
12850                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12851                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12852                         if (mb) {
12853                                 check_array_for_usertypes (mb->parameters, &error);
12854                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12855                                 if (mb->param_modreq)
12856                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12857                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12858                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12859                                         }
12860                                 if (mb->param_modopt)
12861                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12862                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12863                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12864                                         }
12865                         }
12866                 }
12867         }
12868
12869         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12870
12871         /* 
12872          * we need to lock the domain because the lock will be taken inside
12873          * So, we need to keep the locking order correct.
12874          */
12875         mono_loader_lock ();
12876         mono_domain_lock (domain);
12877         if (klass->wastypebuilder) {
12878                 mono_domain_unlock (domain);
12879                 mono_loader_unlock ();
12880
12881                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12882                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12883
12884                 return res;
12885         }
12886         /*
12887          * Fields to set in klass:
12888          * the various flags: delegate/unicode/contextbound etc.
12889          */
12890         klass->flags = tb->attrs;
12891         klass->has_cctor = 1;
12892         klass->has_finalize = 1;
12893         klass->has_finalize_inited = 1;
12894
12895         mono_class_setup_parent (klass, klass->parent);
12896         /* fool mono_class_setup_supertypes */
12897         klass->supertypes = NULL;
12898         mono_class_setup_supertypes (klass);
12899         mono_class_setup_mono_type (klass);
12900
12901 #if 0
12902         if (!((MonoDynamicImage*)klass->image)->run) {
12903                 if (klass->generic_container) {
12904                         /* FIXME: The code below can't handle generic classes */
12905                         klass->wastypebuilder = TRUE;
12906                         mono_loader_unlock ();
12907                         mono_domain_unlock (domain);
12908
12909                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12910                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12911
12912                         return res;
12913                 }
12914         }
12915 #endif
12916
12917         /* enums are done right away */
12918         if (!klass->enumtype)
12919                 if (!ensure_runtime_vtable (klass, &error))
12920                         goto failure;
12921
12922         if (tb->subtypes) {
12923                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12924                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12925                         mono_class_alloc_ext (klass);
12926                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12927                         if (!is_ok (&error)) goto failure;
12928                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12929                 }
12930         }
12931
12932         klass->nested_classes_inited = TRUE;
12933
12934         /* fields and object layout */
12935         if (klass->parent) {
12936                 if (!klass->parent->size_inited)
12937                         mono_class_init (klass->parent);
12938                 klass->instance_size = klass->parent->instance_size;
12939                 klass->sizes.class_size = 0;
12940                 klass->min_align = klass->parent->min_align;
12941                 /* if the type has no fields we won't call the field_setup
12942                  * routine which sets up klass->has_references.
12943                  */
12944                 klass->has_references |= klass->parent->has_references;
12945         } else {
12946                 klass->instance_size = sizeof (MonoObject);
12947                 klass->min_align = 1;
12948         }
12949
12950         /* FIXME: handle packing_size and instance_size */
12951         typebuilder_setup_fields (klass, &error);
12952         if (!mono_error_ok (&error))
12953                 goto failure;
12954         typebuilder_setup_properties (klass, &error);
12955         if (!mono_error_ok (&error))
12956                 goto failure;
12957
12958         typebuilder_setup_events (klass, &error);
12959         if (!mono_error_ok (&error))
12960                 goto failure;
12961
12962         klass->wastypebuilder = TRUE;
12963
12964         /* 
12965          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12966          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12967          * we want to return normal System.MonoType objects, so clear these out from the cache.
12968          *
12969          * Together with this we must ensure the contents of all instances to match the created type.
12970          */
12971         if (domain->type_hash && klass->generic_container)
12972                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12973
12974         mono_domain_unlock (domain);
12975         mono_loader_unlock ();
12976
12977         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12978                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12979                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12980         }
12981
12982         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12983         mono_error_raise_exception (&error); /* FIXME don't raise here */
12984
12985         g_assert (res != (MonoReflectionType*)tb);
12986
12987         return res;
12988
12989 failure:
12990         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12991         klass->wastypebuilder = TRUE;
12992         mono_domain_unlock (domain);
12993         mono_loader_unlock ();
12994         mono_error_raise_exception (&error);
12995         return NULL;
12996 }
12997
12998 void
12999 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13000 {
13001         MonoGenericParamFull *param;
13002         MonoImage *image;
13003         MonoClass *pklass;
13004         MonoError error;
13005
13006         image = &gparam->tbuilder->module->dynamic_image->image;
13007
13008         param = mono_image_new0 (image, MonoGenericParamFull, 1);
13009
13010         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
13011         g_assert (mono_error_ok (&error));
13012         param->param.num = gparam->index;
13013
13014         if (gparam->mbuilder) {
13015                 if (!gparam->mbuilder->generic_container) {
13016                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
13017                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13018
13019                         MonoClass *klass = mono_class_from_mono_type (tb);
13020                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13021                         gparam->mbuilder->generic_container->is_method = TRUE;
13022                         /* 
13023                          * Cannot set owner.method, since the MonoMethod is not created yet.
13024                          * Set the image field instead, so type_in_image () works.
13025                          */
13026                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13027                         gparam->mbuilder->generic_container->owner.image = klass->image;
13028                 }
13029                 param->param.owner = gparam->mbuilder->generic_container;
13030         } else if (gparam->tbuilder) {
13031                 if (!gparam->tbuilder->generic_container) {
13032                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
13033                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13034                         MonoClass *klass = mono_class_from_mono_type (tb);
13035                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13036                         gparam->tbuilder->generic_container->owner.klass = klass;
13037                 }
13038                 param->param.owner = gparam->tbuilder->generic_container;
13039         }
13040
13041         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13042
13043         gparam->type.type = &pklass->byval_arg;
13044
13045         mono_class_set_ref_info (pklass, gparam);
13046         mono_image_append_class_to_reflection_info_set (pklass);
13047 }
13048
13049 MonoArray *
13050 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13051 {
13052         MonoError error;
13053         MonoReflectionModuleBuilder *module = sig->module;
13054         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13055         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13056         guint32 buflen, i;
13057         MonoArray *result;
13058         SigBuffer buf;
13059
13060         check_array_for_usertypes (sig->arguments, &error);
13061         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13062
13063         sigbuffer_init (&buf, 32);
13064
13065         sigbuffer_add_value (&buf, 0x07);
13066         sigbuffer_add_value (&buf, na);
13067         if (assembly != NULL){
13068                 for (i = 0; i < na; ++i) {
13069                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13070                         encode_reflection_type (assembly, type, &buf, &error);
13071                         if (!is_ok (&error)) goto fail;
13072                 }
13073         }
13074
13075         buflen = buf.p - buf.buf;
13076         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13077         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13078         sigbuffer_free (&buf);
13079         return result;
13080 fail:
13081         sigbuffer_free (&buf);
13082         mono_error_raise_exception (&error); /* FIXME don't raise here */
13083         return NULL;
13084 }
13085
13086 MonoArray *
13087 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13088 {
13089         MonoError error;
13090         MonoDynamicImage *assembly = sig->module->dynamic_image;
13091         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13092         guint32 buflen, i;
13093         MonoArray *result;
13094         SigBuffer buf;
13095
13096         check_array_for_usertypes (sig->arguments, &error);
13097         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13098
13099         sigbuffer_init (&buf, 32);
13100
13101         sigbuffer_add_value (&buf, 0x06);
13102         for (i = 0; i < na; ++i) {
13103                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13104                 encode_reflection_type (assembly, type, &buf, &error);
13105                 if (!is_ok (&error))
13106                         goto fail;
13107         }
13108
13109         buflen = buf.p - buf.buf;
13110         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13111         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13112         sigbuffer_free (&buf);
13113
13114         return result;
13115 fail:
13116         sigbuffer_free (&buf);
13117         mono_error_raise_exception (&error); /* FIXME don't raise here */
13118         return NULL;
13119 }
13120
13121 typedef struct {
13122         MonoMethod *handle;
13123         MonoDomain *domain;
13124 } DynamicMethodReleaseData;
13125
13126 /*
13127  * The runtime automatically clean up those after finalization.
13128 */      
13129 static MonoReferenceQueue *dynamic_method_queue;
13130
13131 static void
13132 free_dynamic_method (void *dynamic_method)
13133 {
13134         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13135         MonoDomain *domain = data->domain;
13136         MonoMethod *method = data->handle;
13137         guint32 dis_link;
13138
13139         mono_domain_lock (domain);
13140         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13141         g_hash_table_remove (domain->method_to_dyn_method, method);
13142         mono_domain_unlock (domain);
13143         g_assert (dis_link);
13144         mono_gchandle_free (dis_link);
13145
13146         mono_runtime_free_method (domain, method);
13147         g_free (data);
13148 }
13149
13150 void 
13151 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13152 {
13153         MonoError error;
13154         MonoReferenceQueue *queue;
13155         MonoMethod *handle;
13156         DynamicMethodReleaseData *release_data;
13157         ReflectionMethodBuilder rmb;
13158         MonoMethodSignature *sig;
13159         MonoClass *klass;
13160         MonoDomain *domain;
13161         GSList *l;
13162         int i;
13163
13164         if (mono_runtime_is_shutting_down ())
13165                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13166
13167         if (!(queue = dynamic_method_queue)) {
13168                 mono_loader_lock ();
13169                 if (!(queue = dynamic_method_queue))
13170                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13171                 mono_loader_unlock ();
13172         }
13173
13174         sig = dynamic_method_to_signature (mb);
13175
13176         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13177
13178         /*
13179          * Resolve references.
13180          */
13181         /* 
13182          * Every second entry in the refs array is reserved for storing handle_class,
13183          * which is needed by the ldtoken implementation in the JIT.
13184          */
13185         rmb.nrefs = mb->nrefs;
13186         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13187         for (i = 0; i < mb->nrefs; i += 2) {
13188                 MonoClass *handle_class;
13189                 gpointer ref;
13190                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13191
13192                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13193                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13194                         /*
13195                          * The referenced DynamicMethod should already be created by the managed
13196                          * code, except in the case of circular references. In that case, we store
13197                          * method in the refs array, and fix it up later when the referenced 
13198                          * DynamicMethod is created.
13199                          */
13200                         if (method->mhandle) {
13201                                 ref = method->mhandle;
13202                         } else {
13203                                 /* FIXME: GC object stored in unmanaged memory */
13204                                 ref = method;
13205
13206                                 /* FIXME: GC object stored in unmanaged memory */
13207                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13208                         }
13209                         handle_class = mono_defaults.methodhandle_class;
13210                 } else {
13211                         MonoException *ex = NULL;
13212                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13213                         if (!ref)
13214                                 ex = mono_get_exception_type_load (NULL, NULL);
13215                         else if (mono_security_core_clr_enabled ())
13216                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13217
13218                         if (ex) {
13219                                 g_free (rmb.refs);
13220                                 mono_raise_exception (ex);
13221                                 return;
13222                         }
13223                 }
13224
13225                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13226                 rmb.refs [i + 1] = handle_class;
13227         }               
13228
13229         if (mb->owner) {
13230                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13231                 if (!is_ok (&error)) {
13232                         g_free (rmb.refs);
13233                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13234                 }
13235                 klass = mono_class_from_mono_type (owner_type);
13236         } else {
13237                 klass = mono_defaults.object_class;
13238         }
13239
13240         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13241         release_data = g_new (DynamicMethodReleaseData, 1);
13242         release_data->handle = handle;
13243         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13244         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13245                 g_free (release_data);
13246
13247         /* Fix up refs entries pointing at us */
13248         for (l = mb->referenced_by; l; l = l->next) {
13249                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13250                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13251                 gpointer *data;
13252                 
13253                 g_assert (method->mhandle);
13254
13255                 data = (gpointer*)wrapper->method_data;
13256                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13257                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13258                                 data [i + 1] = mb->mhandle;
13259                 }
13260         }
13261         g_slist_free (mb->referenced_by);
13262
13263         g_free (rmb.refs);
13264
13265         /* ilgen is no longer needed */
13266         mb->ilgen = NULL;
13267
13268         domain = mono_domain_get ();
13269         mono_domain_lock (domain);
13270         if (!domain->method_to_dyn_method)
13271                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13272         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13273         mono_domain_unlock (domain);
13274 }
13275
13276 #endif /* DISABLE_REFLECTION_EMIT */
13277
13278 /**
13279  * 
13280  * mono_reflection_is_valid_dynamic_token:
13281  * 
13282  * Returns TRUE if token is valid.
13283  * 
13284  */
13285 gboolean
13286 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13287 {
13288         return lookup_dyn_token (image, token) != NULL;
13289 }
13290
13291 MonoMethodSignature *
13292 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13293 {
13294         MonoMethodSignature *sig;
13295         g_assert (image_is_dynamic (image));
13296
13297         mono_error_init (error);
13298
13299         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13300         if (sig)
13301                 return sig;
13302
13303         return mono_method_signature_checked (method, error);
13304 }
13305
13306 #ifndef DISABLE_REFLECTION_EMIT
13307
13308 /**
13309  * mono_reflection_lookup_dynamic_token:
13310  *
13311  * Finish the Builder object pointed to by TOKEN and return the corresponding
13312  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13313  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13314  * mapping table.
13315  *
13316  * LOCKING: Take the loader lock
13317  */
13318 gpointer
13319 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13320 {
13321         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13322         MonoObject *obj;
13323         MonoClass *klass;
13324
13325         obj = lookup_dyn_token (assembly, token);
13326         if (!obj) {
13327                 if (valid_token)
13328                         g_error ("Could not find required dynamic token 0x%08x", token);
13329                 else
13330                         return NULL;
13331         }
13332
13333         if (!handle_class)
13334                 handle_class = &klass;
13335         return resolve_object (image, obj, handle_class, context);
13336 }
13337
13338 /*
13339  * ensure_complete_type:
13340  *
13341  *   Ensure that KLASS is completed if it is a dynamic type, or references
13342  * dynamic types.
13343  */
13344 static void
13345 ensure_complete_type (MonoClass *klass)
13346 {
13347         MonoError error;
13348
13349         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13350                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13351
13352                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13353                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13354
13355                 // Asserting here could break a lot of code
13356                 //g_assert (klass->wastypebuilder);
13357         }
13358
13359         if (klass->generic_class) {
13360                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13361                 int i;
13362
13363                 for (i = 0; i < inst->type_argc; ++i) {
13364                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13365                 }
13366         }
13367 }
13368
13369 static gpointer
13370 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13371 {
13372         MonoError error;
13373         gpointer result = NULL;
13374
13375         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13376                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13377                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13378                 *handle_class = mono_defaults.string_class;
13379                 g_assert (result);
13380         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13381                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13382                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13383                 MonoClass *mc = mono_class_from_mono_type (type);
13384                 if (!mono_class_init (mc))
13385                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13386
13387                 if (context) {
13388                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13389                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13390
13391                         result = mono_class_from_mono_type (inflated);
13392                         mono_metadata_free_type (inflated);
13393                 } else {
13394                         result = mono_class_from_mono_type (type);
13395                 }
13396                 *handle_class = mono_defaults.typehandle_class;
13397                 g_assert (result);
13398         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13399                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13400                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13401                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13402                 result = ((MonoReflectionMethod*)obj)->method;
13403                 if (context) {
13404                         MonoError error;
13405                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13406                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13407                 }
13408                 *handle_class = mono_defaults.methodhandle_class;
13409                 g_assert (result);
13410         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13411                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13412                 result = mb->mhandle;
13413                 if (!result) {
13414                         /* Type is not yet created */
13415                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13416
13417                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13418                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13419
13420                         /*
13421                          * Hopefully this has been filled in by calling CreateType() on the
13422                          * TypeBuilder.
13423                          */
13424                         /*
13425                          * TODO: This won't work if the application finishes another 
13426                          * TypeBuilder instance instead of this one.
13427                          */
13428                         result = mb->mhandle;
13429                 }
13430                 if (context) {
13431                         MonoError error;
13432                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13433                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13434                 }
13435                 *handle_class = mono_defaults.methodhandle_class;
13436         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13437                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13438
13439                 result = cb->mhandle;
13440                 if (!result) {
13441                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13442
13443                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13444                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13445                         result = cb->mhandle;
13446                 }
13447                 if (context) {
13448                         MonoError error;
13449                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13450                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13451                 }
13452                 *handle_class = mono_defaults.methodhandle_class;
13453         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13454                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13455
13456                 ensure_complete_type (field->parent);
13457                 if (context) {
13458                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13459                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13460
13461                         MonoClass *klass = mono_class_from_mono_type (inflated);
13462                         MonoClassField *inflated_field;
13463                         gpointer iter = NULL;
13464                         mono_metadata_free_type (inflated);
13465                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13466                                 if (!strcmp (field->name, inflated_field->name))
13467                                         break;
13468                         }
13469                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13470                         result = inflated_field;
13471                 } else {
13472                         result = field;
13473                 }
13474                 *handle_class = mono_defaults.fieldhandle_class;
13475                 g_assert (result);
13476         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13477                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13478                 result = fb->handle;
13479
13480                 if (!result) {
13481                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13482
13483                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13484                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13485                         result = fb->handle;
13486                 }
13487
13488                 if (fb->handle && fb->handle->parent->generic_container) {
13489                         MonoClass *klass = fb->handle->parent;
13490                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13491                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13492
13493                         MonoClass *inflated = mono_class_from_mono_type (type);
13494
13495                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13496                         g_assert (result);
13497                         mono_metadata_free_type (type);
13498                 }
13499                 *handle_class = mono_defaults.fieldhandle_class;
13500         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13501                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13502                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13503                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13504                 MonoClass *klass;
13505
13506                 klass = type->data.klass;
13507                 if (klass->wastypebuilder) {
13508                         /* Already created */
13509                         result = klass;
13510                 }
13511                 else {
13512                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13513                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13514                         result = type->data.klass;
13515                         g_assert (result);
13516                 }
13517                 *handle_class = mono_defaults.typehandle_class;
13518         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13519                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13520                 MonoMethodSignature *sig;
13521                 int nargs, i;
13522
13523                 if (helper->arguments)
13524                         nargs = mono_array_length (helper->arguments);
13525                 else
13526                         nargs = 0;
13527
13528                 sig = mono_metadata_signature_alloc (image, nargs);
13529                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13530                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13531
13532                 if (helper->unmanaged_call_conv) { /* unmanaged */
13533                         sig->call_convention = helper->unmanaged_call_conv - 1;
13534                         sig->pinvoke = TRUE;
13535                 } else if (helper->call_conv & 0x02) {
13536                         sig->call_convention = MONO_CALL_VARARG;
13537                 } else {
13538                         sig->call_convention = MONO_CALL_DEFAULT;
13539                 }
13540
13541                 sig->param_count = nargs;
13542                 /* TODO: Copy type ? */
13543                 sig->ret = helper->return_type->type;
13544                 for (i = 0; i < nargs; ++i) {
13545                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13546                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13547                 }
13548
13549                 result = sig;
13550                 *handle_class = NULL;
13551         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13552                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13553                 /* Already created by the managed code */
13554                 g_assert (method->mhandle);
13555                 result = method->mhandle;
13556                 *handle_class = mono_defaults.methodhandle_class;
13557         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13558                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13559                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13560                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13561                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13562
13563                 result = mono_class_from_mono_type (type);
13564                 *handle_class = mono_defaults.typehandle_class;
13565                 g_assert (result);
13566                 mono_metadata_free_type (type);
13567         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13568                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13569                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13570                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13571                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13572
13573                 result = mono_class_from_mono_type (type);
13574                 *handle_class = mono_defaults.typehandle_class;
13575                 g_assert (result);
13576                 mono_metadata_free_type (type);
13577         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13578                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13579                 MonoClass *inflated;
13580                 MonoType *type;
13581                 MonoClassField *field;
13582
13583                 if (is_sre_field_builder (mono_object_class (f->fb)))
13584                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13585                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13586                         field = ((MonoReflectionField*)f->fb)->field;
13587                 else
13588                         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)));
13589
13590                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13591                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13592                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13593                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13594
13595                 inflated = mono_class_from_mono_type (type);
13596
13597                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13598                 ensure_complete_type (field->parent);
13599                 g_assert (result);
13600                 mono_metadata_free_type (type);
13601                 *handle_class = mono_defaults.fieldhandle_class;
13602         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13603                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13604                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13605                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13606                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13607                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13608
13609                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13610                 MonoMethod *method;
13611
13612                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13613                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13614                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13615                         method = ((MonoReflectionMethod *)c->cb)->method;
13616                 else
13617                         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)));
13618
13619                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13620                 *handle_class = mono_defaults.methodhandle_class;
13621                 mono_metadata_free_type (type);
13622         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13623                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13624                 if (m->method_args) {
13625                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13626                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13627                         if (context) {
13628                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13629                                 mono_error_assert_ok (&error);
13630                         }
13631                 } else {
13632                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13633                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13634                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13635                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13636
13637                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13638                         MonoMethod *method;
13639
13640                         if (is_sre_method_builder (mono_object_class (m->mb)))
13641                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13642                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13643                                 method = ((MonoReflectionMethod *)m->mb)->method;
13644                         else
13645                                 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)));
13646
13647                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13648                         mono_metadata_free_type (type);
13649                 }
13650                 *handle_class = mono_defaults.methodhandle_class;
13651         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13652                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13653                 MonoType *mtype;
13654                 MonoClass *klass;
13655                 MonoMethod *method;
13656                 gpointer iter;
13657                 char *name;
13658
13659                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13660                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13661                 klass = mono_class_from_mono_type (mtype);
13662
13663                 /* Find the method */
13664
13665                 name = mono_string_to_utf8 (m->name);
13666                 iter = NULL;
13667                 while ((method = mono_class_get_methods (klass, &iter))) {
13668                         if (!strcmp (method->name, name))
13669                                 break;
13670                 }
13671                 g_free (name);
13672
13673                 // FIXME:
13674                 g_assert (method);
13675                 // FIXME: Check parameters/return value etc. match
13676
13677                 result = method;
13678                 *handle_class = mono_defaults.methodhandle_class;
13679         } else if (is_sre_array (mono_object_get_class(obj)) ||
13680                                 is_sre_byref (mono_object_get_class(obj)) ||
13681                                 is_sre_pointer (mono_object_get_class(obj))) {
13682                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13683                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13684                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13685
13686                 if (context) {
13687                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13688                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13689
13690                         result = mono_class_from_mono_type (inflated);
13691                         mono_metadata_free_type (inflated);
13692                 } else {
13693                         result = mono_class_from_mono_type (type);
13694                 }
13695                 *handle_class = mono_defaults.typehandle_class;
13696         } else {
13697                 g_print ("%s\n", obj->vtable->klass->name);
13698                 g_assert_not_reached ();
13699         }
13700         return result;
13701 }
13702
13703 #else /* DISABLE_REFLECTION_EMIT */
13704
13705 MonoArray*
13706 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13707 {
13708         g_assert_not_reached ();
13709         return NULL;
13710 }
13711
13712 void
13713 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13714 {
13715         g_assert_not_reached ();
13716 }
13717
13718 void
13719 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13720 {
13721         g_assert_not_reached ();
13722 }
13723
13724 void
13725 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13726 {
13727         g_assert_not_reached ();
13728 }
13729
13730 void
13731 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13732 {
13733         g_assert_not_reached ();
13734 }
13735
13736 void
13737 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13738 {
13739         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13740 }
13741
13742 void
13743 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13744 {
13745         g_assert_not_reached ();
13746 }
13747
13748 void
13749 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13750 {
13751         g_assert_not_reached ();
13752 }
13753
13754 MonoReflectionModule *
13755 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13756 {
13757         g_assert_not_reached ();
13758         return NULL;
13759 }
13760
13761 guint32
13762 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13763 {
13764         g_assert_not_reached ();
13765         return 0;
13766 }
13767
13768 guint32
13769 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13770 {
13771         g_assert_not_reached ();
13772         return 0;
13773 }
13774
13775 guint32
13776 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13777                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13778 {
13779         g_assert_not_reached ();
13780         return 0;
13781 }
13782
13783 void
13784 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13785 {
13786 }
13787
13788 void
13789 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13790 {
13791         g_assert_not_reached ();
13792 }
13793
13794 void
13795 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13796 {
13797         *overrides = NULL;
13798         *num_overrides = 0;
13799 }
13800
13801 MonoReflectionEvent *
13802 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13803 {
13804         g_assert_not_reached ();
13805         return NULL;
13806 }
13807
13808 MonoReflectionType*
13809 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13810 {
13811         g_assert_not_reached ();
13812         return NULL;
13813 }
13814
13815 void
13816 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13817 {
13818         g_assert_not_reached ();
13819 }
13820
13821 MonoArray *
13822 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13823 {
13824         g_assert_not_reached ();
13825         return NULL;
13826 }
13827
13828 MonoArray *
13829 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13830 {
13831         g_assert_not_reached ();
13832         return NULL;
13833 }
13834
13835 void 
13836 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13837 {
13838 }
13839
13840 gpointer
13841 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13842 {
13843         return NULL;
13844 }
13845
13846 MonoType*
13847 mono_reflection_type_get_handle (MonoReflectionType* ref)
13848 {
13849         if (!ref)
13850                 return NULL;
13851         return ref->type;
13852 }
13853
13854 void
13855 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13856 {
13857         g_assert_not_reached ();
13858 }
13859
13860 #endif /* DISABLE_REFLECTION_EMIT */
13861
13862 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13863 const static guint32 declsec_flags_map[] = {
13864         0x00000000,                                     /* empty */
13865         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13866         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13867         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13868         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13869         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13870         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13871         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13872         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13873         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13874         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13875         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13876         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13877         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13878         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13879         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13880         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13881         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13882         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13883 };
13884
13885 /*
13886  * Returns flags that includes all available security action associated to the handle.
13887  * @token: metadata token (either for a class or a method)
13888  * @image: image where resides the metadata.
13889  */
13890 static guint32
13891 mono_declsec_get_flags (MonoImage *image, guint32 token)
13892 {
13893         int index = mono_metadata_declsec_from_index (image, token);
13894         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13895         guint32 result = 0;
13896         guint32 action;
13897         int i;
13898
13899         /* HasSecurity can be present for other, not specially encoded, attributes,
13900            e.g. SuppressUnmanagedCodeSecurityAttribute */
13901         if (index < 0)
13902                 return 0;
13903
13904         for (i = index; i < t->rows; i++) {
13905                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13906
13907                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13908                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13909                         break;
13910
13911                 action = cols [MONO_DECL_SECURITY_ACTION];
13912                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13913                         result |= declsec_flags_map [action];
13914                 } else {
13915                         g_assert_not_reached ();
13916                 }
13917         }
13918         return result;
13919 }
13920
13921 /*
13922  * Get the security actions (in the form of flags) associated with the specified method.
13923  *
13924  * @method: The method for which we want the declarative security flags.
13925  * Return the declarative security flags for the method (only).
13926  *
13927  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13928  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13929  */
13930 guint32
13931 mono_declsec_flags_from_method (MonoMethod *method)
13932 {
13933         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13934                 /* FIXME: No cache (for the moment) */
13935                 guint32 idx = mono_method_get_index (method);
13936                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13937                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13938                 return mono_declsec_get_flags (method->klass->image, idx);
13939         }
13940         return 0;
13941 }
13942
13943 /*
13944  * Get the security actions (in the form of flags) associated with the specified class.
13945  *
13946  * @klass: The class for which we want the declarative security flags.
13947  * Return the declarative security flags for the class.
13948  *
13949  * Note: We cache the flags inside the MonoClass structure as this will get 
13950  *       called very often (at least for each method).
13951  */
13952 guint32
13953 mono_declsec_flags_from_class (MonoClass *klass)
13954 {
13955         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13956                 if (!klass->ext || !klass->ext->declsec_flags) {
13957                         guint32 idx;
13958
13959                         idx = mono_metadata_token_index (klass->type_token);
13960                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13961                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13962                         mono_loader_lock ();
13963                         mono_class_alloc_ext (klass);
13964                         mono_loader_unlock ();
13965                         /* we cache the flags on classes */
13966                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13967                 }
13968                 return klass->ext->declsec_flags;
13969         }
13970         return 0;
13971 }
13972
13973 /*
13974  * Get the security actions (in the form of flags) associated with the specified assembly.
13975  *
13976  * @assembly: The assembly for which we want the declarative security flags.
13977  * Return the declarative security flags for the assembly.
13978  */
13979 guint32
13980 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13981 {
13982         guint32 idx = 1; /* there is only one assembly */
13983         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13984         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13985         return mono_declsec_get_flags (assembly->image, idx);
13986 }
13987
13988
13989 /*
13990  * Fill actions for the specific index (which may either be an encoded class token or
13991  * an encoded method token) from the metadata image.
13992  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13993  */
13994 static MonoBoolean
13995 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13996         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13997 {
13998         MonoBoolean result = FALSE;
13999         MonoTableInfo *t;
14000         guint32 cols [MONO_DECL_SECURITY_SIZE];
14001         int index = mono_metadata_declsec_from_index (image, token);
14002         int i;
14003
14004         t  = &image->tables [MONO_TABLE_DECLSECURITY];
14005         for (i = index; i < t->rows; i++) {
14006                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14007
14008                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
14009                         return result;
14010
14011                 /* if present only replace (class) permissions with method permissions */
14012                 /* if empty accept either class or method permissions */
14013                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
14014                         if (!actions->demand.blob) {
14015                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14016                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14017                                 actions->demand.blob = (char*) (blob + 2);
14018                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14019                                 result = TRUE;
14020                         }
14021                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14022                         if (!actions->noncasdemand.blob) {
14023                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14024                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14025                                 actions->noncasdemand.blob = (char*) (blob + 2);
14026                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14027                                 result = TRUE;
14028                         }
14029                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14030                         if (!actions->demandchoice.blob) {
14031                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14032                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14033                                 actions->demandchoice.blob = (char*) (blob + 2);
14034                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14035                                 result = TRUE;
14036                         }
14037                 }
14038         }
14039
14040         return result;
14041 }
14042
14043 static MonoBoolean
14044 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14045         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14046 {
14047         guint32 idx = mono_metadata_token_index (klass->type_token);
14048         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14049         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14050         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14051 }
14052
14053 static MonoBoolean
14054 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14055         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14056 {
14057         guint32 idx = mono_method_get_index (method);
14058         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14059         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14060         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14061 }
14062
14063 /*
14064  * Collect all actions (that requires to generate code in mini) assigned for
14065  * the specified method.
14066  * Note: Don't use the content of actions if the function return FALSE.
14067  */
14068 MonoBoolean
14069 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14070 {
14071         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14072                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14073         MonoBoolean result = FALSE;
14074         guint32 flags;
14075
14076         /* quick exit if no declarative security is present in the metadata */
14077         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14078                 return FALSE;
14079
14080         /* we want the original as the wrapper is "free" of the security informations */
14081         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14082                 method = mono_marshal_method_from_wrapper (method);
14083                 if (!method)
14084                         return FALSE;
14085         }
14086
14087         /* First we look for method-level attributes */
14088         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14089                 mono_class_init (method->klass);
14090                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14091
14092                 result = mono_declsec_get_method_demands_params (method, demands, 
14093                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14094         }
14095
14096         /* Here we use (or create) the class declarative cache to look for demands */
14097         flags = mono_declsec_flags_from_class (method->klass);
14098         if (flags & mask) {
14099                 if (!result) {
14100                         mono_class_init (method->klass);
14101                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14102                 }
14103                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14104                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14105         }
14106
14107         /* The boolean return value is used as a shortcut in case nothing needs to
14108            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14109         return result;
14110 }
14111
14112
14113 /*
14114  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14115  *
14116  * Note: Don't use the content of actions if the function return FALSE.
14117  */
14118 MonoBoolean
14119 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14120 {
14121         MonoBoolean result = FALSE;
14122         guint32 flags;
14123
14124         /* quick exit if no declarative security is present in the metadata */
14125         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14126                 return FALSE;
14127
14128         /* we want the original as the wrapper is "free" of the security informations */
14129         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14130                 method = mono_marshal_method_from_wrapper (method);
14131                 if (!method)
14132                         return FALSE;
14133         }
14134
14135         /* results are independant - zeroize both */
14136         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14137         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14138
14139         /* First we look for method-level attributes */
14140         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14141                 mono_class_init (method->klass);
14142
14143                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14144                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14145         }
14146
14147         /* Here we use (or create) the class declarative cache to look for demands */
14148         flags = mono_declsec_flags_from_class (method->klass);
14149         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14150                 mono_class_init (method->klass);
14151
14152                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14153                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14154         }
14155
14156         return result;
14157 }
14158
14159 /*
14160  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14161  *
14162  * @klass       The inherited class - this is the class that provides the security check (attributes)
14163  * @demans      
14164  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14165  * 
14166  * Note: Don't use the content of actions if the function return FALSE.
14167  */
14168 MonoBoolean
14169 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14170 {
14171         MonoBoolean result = FALSE;
14172         guint32 flags;
14173
14174         /* quick exit if no declarative security is present in the metadata */
14175         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14176                 return FALSE;
14177
14178         /* Here we use (or create) the class declarative cache to look for demands */
14179         flags = mono_declsec_flags_from_class (klass);
14180         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14181                 mono_class_init (klass);
14182                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14183
14184                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14185                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14186         }
14187
14188         return result;
14189 }
14190
14191 /*
14192  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14193  *
14194  * Note: Don't use the content of actions if the function return FALSE.
14195  */
14196 MonoBoolean
14197 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14198 {
14199         /* quick exit if no declarative security is present in the metadata */
14200         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14201                 return FALSE;
14202
14203         /* we want the original as the wrapper is "free" of the security informations */
14204         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14205                 method = mono_marshal_method_from_wrapper (method);
14206                 if (!method)
14207                         return FALSE;
14208         }
14209
14210         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14211                 mono_class_init (method->klass);
14212                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14213
14214                 return mono_declsec_get_method_demands_params (method, demands, 
14215                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14216         }
14217         return FALSE;
14218 }
14219
14220
14221 static MonoBoolean
14222 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14223 {
14224         guint32 cols [MONO_DECL_SECURITY_SIZE];
14225         MonoTableInfo *t;
14226         int i;
14227
14228         int index = mono_metadata_declsec_from_index (image, token);
14229         if (index == -1)
14230                 return FALSE;
14231
14232         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14233         for (i = index; i < t->rows; i++) {
14234                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14235
14236                 /* shortcut - index are ordered */
14237                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14238                         return FALSE;
14239
14240                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14241                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14242                         entry->blob = (char*) (metadata + 2);
14243                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14244                         return TRUE;
14245                 }
14246         }
14247
14248         return FALSE;
14249 }
14250
14251 MonoBoolean
14252 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14253 {
14254         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14255                 guint32 idx = mono_method_get_index (method);
14256                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14257                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14258                 return get_declsec_action (method->klass->image, idx, action, entry);
14259         }
14260         return FALSE;
14261 }
14262
14263 MonoBoolean
14264 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14265 {
14266         /* use cache */
14267         guint32 flags = mono_declsec_flags_from_class (klass);
14268         if (declsec_flags_map [action] & flags) {
14269                 guint32 idx = mono_metadata_token_index (klass->type_token);
14270                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14271                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14272                 return get_declsec_action (klass->image, idx, action, entry);
14273         }
14274         return FALSE;
14275 }
14276
14277 MonoBoolean
14278 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14279 {
14280         guint32 idx = 1; /* there is only one assembly */
14281         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14282         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14283
14284         return get_declsec_action (assembly->image, idx, action, entry);
14285 }
14286
14287 gboolean
14288 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14289 {
14290         MonoError error;
14291         MonoObject *res, *exc;
14292         void *params [1];
14293         static MonoMethod *method = NULL;
14294
14295         if (method == NULL) {
14296                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14297                 g_assert (method);
14298         }
14299
14300         /* 
14301          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14302          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14303          */
14304         g_assert (mono_class_get_ref_info (klass));
14305         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14306
14307         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14308         mono_error_raise_exception (&error); /* FIXME don't raise here */
14309
14310         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14311
14312         if (exc || !mono_error_ok (&error)) {
14313                 mono_error_cleanup (&error);
14314                 return FALSE;
14315         } else
14316                 return *(MonoBoolean*)mono_object_unbox (res);
14317 }
14318
14319 /**
14320  * mono_reflection_type_get_type:
14321  * @reftype: the System.Type object
14322  *
14323  * Returns the MonoType* associated with the C# System.Type object @reftype.
14324  */
14325 MonoType*
14326 mono_reflection_type_get_type (MonoReflectionType *reftype)
14327 {
14328         g_assert (reftype);
14329
14330         MonoError error;
14331         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14332         mono_error_assert_ok (&error);
14333         return result;
14334 }
14335
14336 /**
14337  * mono_reflection_assembly_get_assembly:
14338  * @refassembly: the System.Reflection.Assembly object
14339  *
14340  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14341  */
14342 MonoAssembly*
14343 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14344 {
14345         g_assert (refassembly);
14346
14347         return refassembly->assembly;
14348 }
14349