[SRE] MonoError in property_encode_signature
[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);
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);
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)
2475 {
2476         MONO_REQ_GC_UNSAFE_MODE;
2477
2478         MonoError error;
2479         MonoDynamicTable *table;
2480         guint32 *values;
2481         guint num_methods = 0;
2482         guint32 semaidx;
2483
2484         /* 
2485          * we need to set things in the following tables:
2486          * EVENTMAP (info already filled in _get_type_info ())
2487          * EVENT    (rows already preallocated in _get_type_info ())
2488          * METHOD      (method info already done with the generic method code)
2489          * METHODSEMANTICS
2490          */
2491         table = &assembly->tables [MONO_TABLE_EVENT];
2492         eb->table_idx = table->next_idx ++;
2493         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2494         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2495         values [MONO_EVENT_FLAGS] = eb->attrs;
2496         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, &error);
2497         mono_error_raise_exception (&error); /* FIXME don't raise here */
2498         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2499
2500         /*
2501          * FIXME: we still don't handle 'other' methods 
2502          */
2503         if (eb->add_method) num_methods ++;
2504         if (eb->remove_method) num_methods ++;
2505         if (eb->raise_method) num_methods ++;
2506
2507         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2508         table->rows += num_methods;
2509         alloc_table (table, table->rows);
2510
2511         if (eb->add_method) {
2512                 semaidx = table->next_idx ++;
2513                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2514                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2515                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2516                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2517         }
2518         if (eb->remove_method) {
2519                 semaidx = table->next_idx ++;
2520                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2521                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2522                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2523                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2524         }
2525         if (eb->raise_method) {
2526                 semaidx = table->next_idx ++;
2527                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2528                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2529                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2530                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2531         }
2532 }
2533
2534 static void
2535 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2536 {
2537         MONO_REQ_GC_UNSAFE_MODE;
2538
2539         MonoError error;
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                 mono_error_raise_exception (&error); /* FIXME don't raise here */
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                 mono_error_raise_exception (&error); /* FIXME don't raise here */
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);
2631
2632         return TRUE;
2633 }
2634
2635 static guint32
2636 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2637 {
2638         MONO_REQ_GC_UNSAFE_MODE;
2639
2640         MonoDynamicTable *table;
2641         guint32 token;
2642         guint32 *values;
2643         guint32 cols [MONO_ASSEMBLY_SIZE];
2644         const char *pubkey;
2645         guint32 publen;
2646
2647         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2648                 return token;
2649
2650         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2651                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2652                 token = table->next_idx ++;
2653                 table->rows ++;
2654                 alloc_table (table, table->rows);
2655                 values = table->values + token * MONO_MODULEREF_SIZE;
2656                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2657
2658                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2659                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2660                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2661
2662                 return token;
2663         }
2664         
2665         if (assembly_is_dynamic (image->assembly))
2666                 /* FIXME: */
2667                 memset (cols, 0, sizeof (cols));
2668         else {
2669                 /* image->assembly->image is the manifest module */
2670                 image = image->assembly->image;
2671                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2672         }
2673
2674         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2675         token = table->next_idx ++;
2676         table->rows ++;
2677         alloc_table (table, table->rows);
2678         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2679         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2680         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2681         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2682         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2683         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2684         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2685         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2686         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2687
2688         if (strcmp ("", image->assembly->aname.culture)) {
2689                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2690                                 image->assembly->aname.culture);
2691         }
2692
2693         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2694                 guchar pubtoken [9];
2695                 pubtoken [0] = 8;
2696                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2697                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2698         } else {
2699                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2700         }
2701         token <<= MONO_RESOLUTION_SCOPE_BITS;
2702         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2703         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2704         return token;
2705 }
2706
2707 static guint32
2708 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2709 {
2710         MONO_REQ_GC_NEUTRAL_MODE;
2711
2712         MonoDynamicTable *table;
2713         guint32 *values;
2714         guint32 token;
2715         SigBuffer buf;
2716
2717         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2718                 return token;
2719
2720         sigbuffer_init (&buf, 32);
2721         switch (type->type) {
2722         case MONO_TYPE_FNPTR:
2723         case MONO_TYPE_PTR:
2724         case MONO_TYPE_SZARRAY:
2725         case MONO_TYPE_ARRAY:
2726         case MONO_TYPE_VAR:
2727         case MONO_TYPE_MVAR:
2728         case MONO_TYPE_GENERICINST:
2729                 encode_type (assembly, type, &buf);
2730                 break;
2731         case MONO_TYPE_CLASS:
2732         case MONO_TYPE_VALUETYPE: {
2733                 MonoClass *k = mono_class_from_mono_type (type);
2734                 if (!k || !k->generic_container) {
2735                         sigbuffer_free (&buf);
2736                         return 0;
2737                 }
2738                 encode_type (assembly, type, &buf);
2739                 break;
2740         }
2741         default:
2742                 sigbuffer_free (&buf);
2743                 return 0;
2744         }
2745
2746         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2747         if (assembly->save) {
2748                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2749                 alloc_table (table, table->rows + 1);
2750                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2751                 values [MONO_TYPESPEC_SIGNATURE] = token;
2752         }
2753         sigbuffer_free (&buf);
2754
2755         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2756         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2757         table->next_idx ++;
2758         return token;
2759 }
2760
2761 static guint32
2762 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2763 {
2764         MONO_REQ_GC_UNSAFE_MODE;
2765
2766         MonoDynamicTable *table;
2767         guint32 *values;
2768         guint32 token, scope, enclosing;
2769         MonoClass *klass;
2770
2771         /* if the type requires a typespec, we must try that first*/
2772         if (try_typespec && (token = create_typespec (assembly, type)))
2773                 return token;
2774         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2775         if (token)
2776                 return token;
2777         klass = mono_class_from_mono_type (type);
2778         if (!klass)
2779                 klass = mono_class_from_mono_type (type);
2780
2781         /*
2782          * If it's in the same module and not a generic type parameter:
2783          */
2784         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2785                         (type->type != MONO_TYPE_MVAR)) {
2786                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2787                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2788                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2789                 return token;
2790         }
2791
2792         if (klass->nested_in) {
2793                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2794                 /* get the typeref idx of the enclosing type */
2795                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2796                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2797         } else {
2798                 scope = resolution_scope_from_image (assembly, klass->image);
2799         }
2800         table = &assembly->tables [MONO_TABLE_TYPEREF];
2801         if (assembly->save) {
2802                 alloc_table (table, table->rows + 1);
2803                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2804                 values [MONO_TYPEREF_SCOPE] = scope;
2805                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2806                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2807         }
2808         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2809         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2810         table->next_idx ++;
2811         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2812         return token;
2813 }
2814
2815 /*
2816  * Despite the name, we handle also TypeSpec (with the above helper).
2817  */
2818 static guint32
2819 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2820 {
2821         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2822 }
2823
2824 #ifndef DISABLE_REFLECTION_EMIT
2825 static guint32
2826 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2827 {
2828         MONO_REQ_GC_NEUTRAL_MODE;
2829
2830         MonoDynamicTable *table;
2831         guint32 *values;
2832         guint32 token, pclass;
2833
2834         switch (parent & MONO_TYPEDEFORREF_MASK) {
2835         case MONO_TYPEDEFORREF_TYPEREF:
2836                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2837                 break;
2838         case MONO_TYPEDEFORREF_TYPESPEC:
2839                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2840                 break;
2841         case MONO_TYPEDEFORREF_TYPEDEF:
2842                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2843                 break;
2844         default:
2845                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2846                 return 0;
2847         }
2848         /* extract the index */
2849         parent >>= MONO_TYPEDEFORREF_BITS;
2850
2851         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2852
2853         if (assembly->save) {
2854                 alloc_table (table, table->rows + 1);
2855                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2856                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2857                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2858                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2859         }
2860
2861         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2862         table->next_idx ++;
2863
2864         return token;
2865 }
2866
2867 /*
2868  * Insert a memberef row into the metadata: the token that point to the memberref
2869  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2870  * mono_image_get_fieldref_token()).
2871  * The sig param is an index to an already built signature.
2872  */
2873 static guint32
2874 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2875 {
2876         MONO_REQ_GC_NEUTRAL_MODE;
2877
2878         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2879         return mono_image_add_memberef_row (assembly, parent, name, sig);
2880 }
2881
2882
2883 static guint32
2884 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2885 {
2886         MONO_REQ_GC_NEUTRAL_MODE;
2887
2888         guint32 token;
2889         MonoMethodSignature *sig;
2890         
2891         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2892
2893         if (create_typespec) {
2894                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2895                 if (token)
2896                         return token;
2897         } 
2898
2899         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2900         if (token && !create_typespec)
2901                 return token;
2902
2903         g_assert (!method->is_inflated);
2904         if (!token) {
2905                 /*
2906                  * A methodref signature can't contain an unmanaged calling convention.
2907                  */
2908                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2909                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2910                         sig->call_convention = MONO_CALL_DEFAULT;
2911                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2912                         method->name,  method_encode_signature (assembly, sig));
2913                 g_free (sig);
2914                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2915         }
2916
2917         if (create_typespec) {
2918                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2919                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2920                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2921
2922                 if (assembly->save) {
2923                         guint32 *values;
2924
2925                         alloc_table (table, table->rows + 1);
2926                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2927                         values [MONO_METHODSPEC_METHOD] = token;
2928                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2929                 }
2930
2931                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2932                 table->next_idx ++;
2933                 /*methodspec and memberef tokens are diferent, */
2934                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2935                 return token;
2936         }
2937         return token;
2938 }
2939
2940 static guint32
2941 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2942 {
2943         guint32 token, parent, sig;
2944         ReflectionMethodBuilder rmb;
2945         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2946         
2947         mono_error_init (error);
2948         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2949         if (token)
2950                 return token;
2951
2952         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2953                 return 0;
2954
2955         /*
2956          * A methodref signature can't contain an unmanaged calling convention.
2957          * Since some flags are encoded as part of call_conv, we need to check against it.
2958         */
2959         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2960                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2961
2962         sig = method_builder_encode_signature (assembly, &rmb, error);
2963         return_val_if_nok (error, 0);
2964
2965         if (tb->generic_params)
2966                 parent = create_generic_typespec (assembly, tb);
2967         else {
2968                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2969                 return_val_if_nok (error, 0);
2970
2971                 parent = mono_image_typedef_or_ref (assembly, t);
2972         }
2973
2974         char *name = mono_string_to_utf8 (method->name);
2975
2976         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2977         g_free (name);
2978
2979         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2980
2981         return token;
2982 }
2983
2984 static guint32
2985 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2986                                      const gchar *name, guint32 sig)
2987 {
2988         MonoDynamicTable *table;
2989         guint32 token;
2990         guint32 *values;
2991         
2992         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2993
2994         if (assembly->save) {
2995                 alloc_table (table, table->rows + 1);
2996                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2997                 values [MONO_MEMBERREF_CLASS] = original;
2998                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2999                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3000         }
3001
3002         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3003         table->next_idx ++;
3004
3005         return token;
3006 }
3007
3008 static guint32
3009 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3010 {
3011         SigBuffer buf;
3012         int i;
3013         guint32 nparams = mono_array_length (mb->generic_params);
3014         guint32 idx;
3015
3016         if (!assembly->save)
3017                 return 0;
3018
3019         sigbuffer_init (&buf, 32);
3020
3021         sigbuffer_add_value (&buf, 0xa);
3022         sigbuffer_add_value (&buf, nparams);
3023
3024         for (i = 0; i < nparams; i++) {
3025                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3026                 sigbuffer_add_value (&buf, i);
3027         }
3028
3029         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3030         sigbuffer_free (&buf);
3031         return idx;
3032 }
3033
3034 static guint32
3035 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3036 {
3037         MonoDynamicTable *table;
3038         guint32 *values;
3039         guint32 token, mtoken = 0;
3040
3041         mono_error_init (error);
3042         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3043         if (token)
3044                 return token;
3045
3046         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3047
3048         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3049         if (!mono_error_ok (error))
3050                 return 0;
3051
3052         switch (mono_metadata_token_table (mtoken)) {
3053         case MONO_TABLE_MEMBERREF:
3054                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3055                 break;
3056         case MONO_TABLE_METHOD:
3057                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3058                 break;
3059         default:
3060                 g_assert_not_reached ();
3061         }
3062
3063         if (assembly->save) {
3064                 alloc_table (table, table->rows + 1);
3065                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3066                 values [MONO_METHODSPEC_METHOD] = mtoken;
3067                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3068         }
3069
3070         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3071         table->next_idx ++;
3072
3073         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3074         return token;
3075 }
3076
3077 static guint32
3078 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3079 {
3080         guint32 token;
3081
3082         mono_error_init (error);
3083
3084         if (mb->generic_params && create_methodspec) 
3085                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3086
3087         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3088         if (token)
3089                 return token;
3090
3091         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3092         if (!mono_error_ok (error))
3093                 return 0;
3094         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3095         return token;
3096 }
3097
3098 static guint32
3099 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3100 {
3101         guint32 token, parent, sig;
3102         ReflectionMethodBuilder rmb;
3103         char *name;
3104         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3105         
3106         mono_error_init (error);
3107         
3108         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3109         if (token)
3110                 return token;
3111
3112         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3113                 return 0;
3114
3115         if (tb->generic_params)
3116                 parent = create_generic_typespec (assembly, tb);
3117         else {
3118                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3119                 return_val_if_nok (error, 0);
3120                 parent = mono_image_typedef_or_ref (assembly, type);
3121         }
3122         
3123         name = mono_string_to_utf8 (rmb.name);
3124         sig = method_builder_encode_signature (assembly, &rmb, error);
3125         return_val_if_nok (error, 0);
3126
3127         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3128
3129         g_free (name);
3130         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3131         return token;
3132 }
3133 #endif
3134
3135 static gboolean
3136 is_field_on_inst (MonoClassField *field)
3137 {
3138         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3139 }
3140
3141 /*
3142  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3143  */
3144 static MonoType*
3145 get_field_on_inst_generic_type (MonoClassField *field)
3146 {
3147         MonoClass *klass, *gtd;
3148         MonoDynamicGenericClass *dgclass;
3149         int field_index;
3150
3151         g_assert (is_field_on_inst (field));
3152
3153         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3154
3155         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3156                 field_index = field - dgclass->fields;
3157                 return dgclass->field_generic_types [field_index];              
3158         }
3159
3160         klass = field->parent;
3161         gtd = klass->generic_class->container_class;
3162
3163         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3164                 field_index = field - klass->fields;
3165                 return gtd->fields [field_index].type;
3166         }
3167
3168         g_assert_not_reached ();
3169         return 0;
3170 }
3171
3172 #ifndef DISABLE_REFLECTION_EMIT
3173 static guint32
3174 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3175 {
3176         MonoType *type;
3177         guint32 token;
3178
3179         g_assert (field);
3180         g_assert (field->parent);
3181
3182         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3183         if (token)
3184                 return token;
3185
3186         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3187                 int index = field - field->parent->fields;
3188                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3189         } else {
3190                 if (is_field_on_inst (field))
3191                         type = get_field_on_inst_generic_type (field);
3192                 else
3193                         type = mono_field_get_type (field);
3194         }
3195         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3196                                                                                         mono_field_get_name (field),
3197                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3198         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3199         return token;
3200 }
3201
3202 static guint32
3203 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3204 {
3205         MonoError error;
3206         guint32 token;
3207         MonoClass *klass;
3208         MonoGenericClass *gclass;
3209         MonoType *type;
3210         char *name;
3211
3212         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3213         if (token)
3214                 return token;
3215         if (is_sre_field_builder (mono_object_class (f->fb))) {
3216                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3217                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3218                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3219                 klass = mono_class_from_mono_type (type);
3220                 gclass = type->data.generic_class;
3221                 g_assert (gclass->is_dynamic);
3222
3223                 name = mono_string_to_utf8 (fb->name);
3224                 guint32 sig_token = field_encode_signature (assembly, fb, &error);
3225                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3226                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3227                 g_free (name);          
3228         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3229                 guint32 sig;
3230                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3231
3232                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
3233                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3234                 klass = mono_class_from_mono_type (type);
3235
3236                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3237                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3238         } else {
3239                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3240                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3241         }
3242
3243         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3244         return token;
3245 }
3246
3247 static guint32
3248 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3249 {
3250         guint32 sig, token;
3251         MonoClass *klass;
3252         MonoGenericClass *gclass;
3253         MonoType *type;
3254
3255         mono_error_init (error);
3256
3257         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3258
3259         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3260         if (token)
3261                 return token;
3262
3263         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3264                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3265                 ReflectionMethodBuilder rmb;
3266                 char *name;
3267
3268                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3269                 return_val_if_nok (error, 0);
3270                 klass = mono_class_from_mono_type (type);
3271
3272                 gclass = type->data.generic_class;
3273                 g_assert (gclass->is_dynamic);
3274
3275                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3276                         return 0;
3277
3278                 sig = method_builder_encode_signature (assembly, &rmb, error);
3279                 return_val_if_nok (error, 0);
3280
3281                 name = mono_string_to_utf8 (rmb.name);
3282
3283                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3284                 g_free (name);
3285         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3286                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3287
3288                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3289                 return_val_if_nok (error, 0);
3290                 klass = mono_class_from_mono_type (type);
3291
3292                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3293                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3294         } else {
3295                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3296                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3297         }
3298
3299
3300         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3301         return token;
3302 }
3303
3304 static MonoMethod*
3305 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3306 {
3307         MonoClass *klass;
3308         MonoGenericContext tmp_context;
3309         MonoType **type_argv;
3310         MonoGenericInst *ginst;
3311         MonoMethod *method, *inflated;
3312         int count, i;
3313
3314         mono_error_init (error);
3315
3316         init_type_builder_generics ((MonoObject*)m->inst);
3317
3318         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3319         return_val_if_nok (error, NULL);
3320
3321         klass = method->klass;
3322
3323         if (m->method_args == NULL)
3324                 return method;
3325
3326         if (method->is_inflated)
3327                 method = ((MonoMethodInflated *) method)->declaring;
3328
3329         count = mono_array_length (m->method_args);
3330
3331         type_argv = g_new0 (MonoType *, count);
3332         for (i = 0; i < count; i++) {
3333                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3334                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3335                 return_val_if_nok (error, NULL);
3336         }
3337         ginst = mono_metadata_get_generic_inst (count, type_argv);
3338         g_free (type_argv);
3339
3340         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3341         tmp_context.method_inst = ginst;
3342
3343         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3344         mono_error_assert_ok (error);
3345         return inflated;
3346 }
3347
3348 static guint32
3349 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3350 {
3351         guint32 sig, token = 0;
3352         MonoType *type;
3353         MonoClass *klass;
3354
3355         mono_error_init (error);
3356
3357         if (m->method_args) {
3358                 MonoMethod *inflated;
3359
3360                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3361                 return_val_if_nok (error, 0);
3362
3363                 if (create_methodspec)
3364                         token = mono_image_get_methodspec_token (assembly, inflated);
3365                 else
3366                         token = mono_image_get_inflated_method_token (assembly, inflated);
3367                 return token;
3368         }
3369
3370         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3371         if (token)
3372                 return token;
3373
3374         if (is_sre_method_builder (mono_object_class (m->mb))) {
3375                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3376                 MonoGenericClass *gclass;
3377                 ReflectionMethodBuilder rmb;
3378                 char *name;
3379
3380                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3381                 return_val_if_nok (error, 0);
3382                 klass = mono_class_from_mono_type (type);
3383                 gclass = type->data.generic_class;
3384                 g_assert (gclass->is_dynamic);
3385
3386                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3387                         return 0;
3388
3389                 sig = method_builder_encode_signature (assembly, &rmb, error);
3390                 return_val_if_nok (error, 0);
3391
3392                 name = mono_string_to_utf8 (rmb.name);
3393
3394                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3395                 g_free (name);          
3396         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3397                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3398
3399                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3400                 return_val_if_nok (error, 0);
3401                 klass = mono_class_from_mono_type (type);
3402
3403                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3404                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3405         } else {
3406                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3407                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3408         }
3409
3410         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3411         return token;
3412 }
3413
3414 static guint32
3415 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3416 {
3417         SigBuffer buf;
3418         int i;
3419         guint32 nparams = context->method_inst->type_argc;
3420         guint32 idx;
3421
3422         if (!assembly->save)
3423                 return 0;
3424
3425         sigbuffer_init (&buf, 32);
3426         /*
3427          * FIXME: vararg, explicit_this, differenc call_conv values...
3428          */
3429         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3430         sigbuffer_add_value (&buf, nparams);
3431
3432         for (i = 0; i < nparams; i++)
3433                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3434
3435         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3436         sigbuffer_free (&buf);
3437         return idx;
3438 }
3439
3440 static guint32
3441 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3442 {
3443         MonoDynamicTable *table;
3444         guint32 *values;
3445         guint32 token, mtoken = 0, sig;
3446         MonoMethodInflated *imethod;
3447         MonoMethod *declaring;
3448
3449         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3450
3451         g_assert (method->is_inflated);
3452         imethod = (MonoMethodInflated *) method;
3453         declaring = imethod->declaring;
3454
3455         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3456         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3457
3458         if (!mono_method_signature (declaring)->generic_param_count)
3459                 return mtoken;
3460
3461         switch (mono_metadata_token_table (mtoken)) {
3462         case MONO_TABLE_MEMBERREF:
3463                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3464                 break;
3465         case MONO_TABLE_METHOD:
3466                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3467                 break;
3468         default:
3469                 g_assert_not_reached ();
3470         }
3471
3472         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3473
3474         if (assembly->save) {
3475                 alloc_table (table, table->rows + 1);
3476                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3477                 values [MONO_METHODSPEC_METHOD] = mtoken;
3478                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3479         }
3480
3481         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3482         table->next_idx ++;
3483
3484         return token;
3485 }
3486
3487 static guint32
3488 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3489 {
3490         MonoMethodInflated *imethod;
3491         guint32 token;
3492         
3493         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3494         if (token)
3495                 return token;
3496
3497         g_assert (method->is_inflated);
3498         imethod = (MonoMethodInflated *) method;
3499
3500         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3501                 token = method_encode_methodspec (assembly, method);
3502         } else {
3503                 guint32 sig = method_encode_signature (
3504                         assembly, mono_method_signature (imethod->declaring));
3505                 token = mono_image_get_memberref_token (
3506                         assembly, &method->klass->byval_arg, method->name, sig);
3507         }
3508
3509         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3510         return token;
3511 }
3512
3513 static guint32
3514 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3515 {
3516         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3517         guint32 sig, token;
3518
3519         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3520         token = mono_image_get_memberref_token (
3521                 assembly, &m->klass->byval_arg, m->name, sig);
3522
3523         return token;
3524 }
3525
3526 static guint32
3527 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3528 {
3529         MonoError error;
3530         MonoDynamicTable *table;
3531         MonoClass *klass;
3532         MonoType *type;
3533         guint32 *values;
3534         guint32 token;
3535         SigBuffer buf;
3536         int count, i;
3537
3538         /*
3539          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3540          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3541          * Because of this, we must not insert it into the `typeref' hash table.
3542          */
3543         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
3544         mono_error_raise_exception (&error); /* FIXME don't raise here */
3545         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3546         if (token)
3547                 return token;
3548
3549         sigbuffer_init (&buf, 32);
3550
3551         g_assert (tb->generic_params);
3552         klass = mono_class_from_mono_type (type);
3553
3554         if (tb->generic_container)
3555                 mono_reflection_create_generic_class (tb);
3556
3557         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3558         g_assert (klass->generic_container);
3559         sigbuffer_add_value (&buf, klass->byval_arg.type);
3560         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3561
3562         count = mono_array_length (tb->generic_params);
3563         sigbuffer_add_value (&buf, count);
3564         for (i = 0; i < count; i++) {
3565                 MonoReflectionGenericParam *gparam;
3566
3567                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3568                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
3569                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3570
3571                 encode_type (assembly, gparam_type, &buf);
3572         }
3573
3574         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3575
3576         if (assembly->save) {
3577                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3578                 alloc_table (table, table->rows + 1);
3579                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3580                 values [MONO_TYPESPEC_SIGNATURE] = token;
3581         }
3582         sigbuffer_free (&buf);
3583
3584         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3585         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3586         table->next_idx ++;
3587         return token;
3588 }
3589
3590 /*
3591  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3592  */
3593 static MonoType*
3594 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3595 {
3596         MonoError error;
3597         int i, count, len, pos;
3598         MonoType *t;
3599
3600         count = 0;
3601         if (modreq)
3602                 count += mono_array_length (modreq);
3603         if (modopt)
3604                 count += mono_array_length (modopt);
3605
3606         if (count == 0)
3607                 return mono_metadata_type_dup (NULL, type);
3608
3609         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3610         t = (MonoType *)g_malloc (len);
3611         memcpy (t, type, MONO_SIZEOF_TYPE);
3612
3613         t->num_mods = count;
3614         pos = 0;
3615         if (modreq) {
3616                 for (i = 0; i < mono_array_length (modreq); ++i) {
3617                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3618                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3619                         t->modifiers [pos].required = 1;
3620                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3621                         pos ++;
3622                 }
3623         }
3624         if (modopt) {
3625                 for (i = 0; i < mono_array_length (modopt); ++i) {
3626                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3627                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3628                         t->modifiers [pos].required = 0;
3629                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3630                         pos ++;
3631                 }
3632         }
3633
3634         return t;
3635 }
3636
3637 static void
3638 init_type_builder_generics (MonoObject *type)
3639 {
3640         MonoReflectionTypeBuilder *tb;
3641
3642         if (!is_sre_type_builder(mono_object_class (type)))
3643                 return;
3644         tb = (MonoReflectionTypeBuilder *)type;
3645
3646         if (tb && tb->generic_container)
3647                 mono_reflection_create_generic_class (tb);
3648 }
3649
3650 static guint32
3651 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3652 {
3653         MonoError error;
3654         MonoDynamicTable *table;
3655         MonoType *custom = NULL, *type;
3656         guint32 *values;
3657         guint32 token, pclass, parent, sig;
3658         gchar *name;
3659
3660         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3661         if (token)
3662                 return token;
3663
3664         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3665         mono_error_raise_exception (&error); /* FIXME don't raise here */
3666         /* FIXME: is this call necessary? */
3667         mono_class_from_mono_type (typeb);
3668         name = mono_string_to_utf8 (fb->name);
3669
3670         /*FIXME this is one more layer of ugliness due how types are created.*/
3671         init_type_builder_generics (fb->type);
3672
3673         /* fb->type does not include the custom modifiers */
3674         /* FIXME: We should do this in one place when a fieldbuilder is created */
3675         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3676         mono_error_raise_exception (&error); /* FIXME don't raise here */
3677
3678         if (fb->modreq || fb->modopt)
3679                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3680
3681         sig = fieldref_encode_signature (assembly, NULL, type);
3682         g_free (custom);
3683
3684         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3685         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3686         
3687         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3688         parent >>= MONO_TYPEDEFORREF_BITS;
3689
3690         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3691
3692         if (assembly->save) {
3693                 alloc_table (table, table->rows + 1);
3694                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3695                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3696                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3697                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3698         }
3699
3700         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3701         table->next_idx ++;
3702         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3703         g_free (name);
3704         return token;
3705 }
3706
3707 static guint32
3708 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3709 {
3710         MonoError error;
3711         SigBuffer buf;
3712         guint32 nargs;
3713         guint32 i, idx;
3714
3715         if (!assembly->save)
3716                 return 0;
3717
3718         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3719         g_assert (helper->type == 2);
3720
3721         if (helper->arguments)
3722                 nargs = mono_array_length (helper->arguments);
3723         else
3724                 nargs = 0;
3725
3726         sigbuffer_init (&buf, 32);
3727
3728         /* Encode calling convention */
3729         /* Change Any to Standard */
3730         if ((helper->call_conv & 0x03) == 0x03)
3731                 helper->call_conv = 0x01;
3732         /* explicit_this implies has_this */
3733         if (helper->call_conv & 0x40)
3734                 helper->call_conv &= 0x20;
3735
3736         if (helper->call_conv == 0) { /* Unmanaged */
3737                 idx = helper->unmanaged_call_conv - 1;
3738         } else {
3739                 /* Managed */
3740                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3741                 if (helper->call_conv & 0x02) /* varargs */
3742                         idx += 0x05;
3743         }
3744
3745         sigbuffer_add_byte (&buf, idx);
3746         sigbuffer_add_value (&buf, nargs);
3747         encode_reflection_type (assembly, helper->return_type, &buf, &error);
3748         if (!is_ok (&error))
3749                 goto fail;
3750         for (i = 0; i < nargs; ++i) {
3751                 MonoArray *modreqs = NULL;
3752                 MonoArray *modopts = NULL;
3753                 MonoReflectionType *pt;
3754
3755                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3756                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3757                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3758                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3759
3760                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3761                 if (!is_ok (&error))
3762                         goto fail;
3763                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3764                 encode_reflection_type (assembly, pt, &buf, &error);
3765                 if (!is_ok (&error))
3766                         goto fail;
3767         }
3768         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3769         sigbuffer_free (&buf);
3770
3771         return idx;
3772 fail:
3773         sigbuffer_free (&buf);
3774         mono_error_raise_exception (&error); /* FIXME don't raise here */
3775         g_assert_not_reached ();
3776 }
3777
3778 static guint32 
3779 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3780 {
3781         guint32 idx;
3782         MonoDynamicTable *table;
3783         guint32 *values;
3784
3785         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3786         idx = table->next_idx ++;
3787         table->rows ++;
3788         alloc_table (table, table->rows);
3789         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3790
3791         values [MONO_STAND_ALONE_SIGNATURE] =
3792                 mono_reflection_encode_sighelper (assembly, helper);
3793
3794         return idx;
3795 }
3796
3797 static int
3798 reflection_cc_to_file (int call_conv) {
3799         switch (call_conv & 0x3) {
3800         case 0:
3801         case 1: return MONO_CALL_DEFAULT;
3802         case 2: return MONO_CALL_VARARG;
3803         default:
3804                 g_assert_not_reached ();
3805         }
3806         return 0;
3807 }
3808 #endif /* !DISABLE_REFLECTION_EMIT */
3809
3810 typedef struct {
3811         MonoType *parent;
3812         MonoMethodSignature *sig;
3813         char *name;
3814         guint32 token;
3815 } ArrayMethod;
3816
3817 #ifndef DISABLE_REFLECTION_EMIT
3818 static guint32
3819 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3820 {
3821         MonoError error;
3822         guint32 nparams, i;
3823         GList *tmp;
3824         char *name;
3825         MonoMethodSignature *sig;
3826         ArrayMethod *am;
3827         MonoType *mtype;
3828
3829         name = mono_string_to_utf8 (m->name);
3830         nparams = mono_array_length (m->parameters);
3831         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3832         sig->hasthis = 1;
3833         sig->sentinelpos = -1;
3834         sig->call_convention = reflection_cc_to_file (m->call_conv);
3835         sig->param_count = nparams;
3836         if (m->ret) {
3837                 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3838                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3839         } else
3840                 sig->ret = &mono_defaults.void_class->byval_arg;
3841
3842         mtype = mono_reflection_type_get_handle (m->parent, &error);
3843         mono_error_raise_exception (&error); /* FIXME don't raise here */
3844
3845         for (i = 0; i < nparams; ++i) {
3846                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3847                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3848         }
3849
3850         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3851                 am = (ArrayMethod *)tmp->data;
3852                 if (strcmp (name, am->name) == 0 && 
3853                                 mono_metadata_type_equal (am->parent, mtype) &&
3854                                 mono_metadata_signature_equal (am->sig, sig)) {
3855                         g_free (name);
3856                         g_free (sig);
3857                         m->table_idx = am->token & 0xffffff;
3858                         return am->token;
3859                 }
3860         }
3861         am = g_new0 (ArrayMethod, 1);
3862         am->name = name;
3863         am->sig = sig;
3864         am->parent = mtype;
3865         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3866                 method_encode_signature (assembly, sig));
3867         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3868         m->table_idx = am->token & 0xffffff;
3869         return am->token;
3870 }
3871
3872 /*
3873  * Insert into the metadata tables all the info about the TypeBuilder tb.
3874  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3875  */
3876 static gboolean
3877 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3878 {
3879         MonoDynamicTable *table;
3880         guint *values;
3881         int i, is_object = 0, is_system = 0;
3882         char *n;
3883
3884         mono_error_init (error);
3885
3886         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3887         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3888         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3889         n = mono_string_to_utf8 (tb->name);
3890         if (strcmp (n, "Object") == 0)
3891                 is_object++;
3892         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3893         g_free (n);
3894         n = mono_string_to_utf8 (tb->nspace);
3895         if (strcmp (n, "System") == 0)
3896                 is_system++;
3897         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3898         g_free (n);
3899         if (tb->parent && !(is_system && is_object) && 
3900                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3901                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3902                 return_val_if_nok (error, FALSE);
3903                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3904         } else {
3905                 values [MONO_TYPEDEF_EXTENDS] = 0;
3906         }
3907         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3908         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3909
3910         /*
3911          * if we have explicitlayout or sequentiallayouts, output data in the
3912          * ClassLayout table.
3913          */
3914         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3915                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3916                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3917                 table->rows++;
3918                 alloc_table (table, table->rows);
3919                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3920                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3921                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3922                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3923         }
3924
3925         /* handle interfaces */
3926         if (tb->interfaces) {
3927                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3928                 i = table->rows;
3929                 table->rows += mono_array_length (tb->interfaces);
3930                 alloc_table (table, table->rows);
3931                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3932                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3933                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3934                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3935                         return_val_if_nok (error, FALSE);
3936                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3937                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3938                         values += MONO_INTERFACEIMPL_SIZE;
3939                 }
3940         }
3941
3942         /* handle fields */
3943         if (tb->fields) {
3944                 table = &assembly->tables [MONO_TABLE_FIELD];
3945                 table->rows += tb->num_fields;
3946                 alloc_table (table, table->rows);
3947                 for (i = 0; i < tb->num_fields; ++i) {
3948                         mono_image_get_field_info (
3949                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3950                         return_val_if_nok (error, FALSE);
3951                 }
3952         }
3953
3954         /* handle constructors */
3955         if (tb->ctors) {
3956                 table = &assembly->tables [MONO_TABLE_METHOD];
3957                 table->rows += mono_array_length (tb->ctors);
3958                 alloc_table (table, table->rows);
3959                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3960                         if (!mono_image_get_ctor_info (domain,
3961                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3962                                                        assembly, error))
3963                                 return FALSE;
3964                 }
3965         }
3966
3967         /* handle methods */
3968         if (tb->methods) {
3969                 table = &assembly->tables [MONO_TABLE_METHOD];
3970                 table->rows += tb->num_methods;
3971                 alloc_table (table, table->rows);
3972                 for (i = 0; i < tb->num_methods; ++i) {
3973                         if (!mono_image_get_method_info (
3974                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3975                                 return FALSE;
3976                 }
3977         }
3978
3979         /* Do the same with properties etc.. */
3980         if (tb->events && mono_array_length (tb->events)) {
3981                 table = &assembly->tables [MONO_TABLE_EVENT];
3982                 table->rows += mono_array_length (tb->events);
3983                 alloc_table (table, table->rows);
3984                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3985                 table->rows ++;
3986                 alloc_table (table, table->rows);
3987                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3988                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3989                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3990                 for (i = 0; i < mono_array_length (tb->events); ++i)
3991                         mono_image_get_event_info (
3992                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3993         }
3994         if (tb->properties && mono_array_length (tb->properties)) {
3995                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3996                 table->rows += mono_array_length (tb->properties);
3997                 alloc_table (table, table->rows);
3998                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3999                 table->rows ++;
4000                 alloc_table (table, table->rows);
4001                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4002                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4003                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4004                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4005                         mono_image_get_property_info (
4006                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4007                         return_val_if_nok (error, FALSE);
4008                 }
4009         }
4010
4011         /* handle generic parameters */
4012         if (tb->generic_params) {
4013                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4014                 table->rows += mono_array_length (tb->generic_params);
4015                 alloc_table (table, table->rows);
4016                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4017                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4018
4019                         mono_image_get_generic_param_info (
4020                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4021                 }
4022         }
4023
4024         mono_image_add_decl_security (assembly, 
4025                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4026
4027         if (tb->subtypes) {
4028                 MonoDynamicTable *ntable;
4029                 
4030                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4031                 ntable->rows += mono_array_length (tb->subtypes);
4032                 alloc_table (ntable, ntable->rows);
4033                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4034
4035                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4036                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4037
4038                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4039                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4040                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4041                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4042                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4043                                 ntable->next_idx, ntable->rows);*/
4044                         values += MONO_NESTED_CLASS_SIZE;
4045                         ntable->next_idx++;
4046                 }
4047         }
4048
4049         return TRUE;
4050 }
4051 #endif
4052
4053 static void
4054 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4055 {
4056         int i;
4057
4058         mono_ptr_array_append (*types, type);
4059
4060         if (!type->subtypes)
4061                 return;
4062
4063         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4064                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4065                 collect_types (types, subtype);
4066         }
4067 }
4068
4069 static gint
4070 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4071 {
4072         if ((*type1)->table_idx < (*type2)->table_idx)
4073                 return -1;
4074         else
4075                 if ((*type1)->table_idx > (*type2)->table_idx)
4076                         return 1;
4077         else
4078                 return 0;
4079 }
4080
4081 static gboolean
4082 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4083         int i;
4084
4085         mono_error_init (error);
4086         if (!pinfo)
4087                 return TRUE;
4088         for (i = 0; i < mono_array_length (pinfo); ++i) {
4089                 MonoReflectionParamBuilder *pb;
4090                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4091                 if (!pb)
4092                         continue;
4093                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4094                         return FALSE;
4095         }
4096
4097         return TRUE;
4098 }
4099
4100 static gboolean
4101 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4102         int i;
4103
4104         mono_error_init (error);
4105         
4106         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4107                 return FALSE;
4108         if (tb->fields) {
4109                 for (i = 0; i < tb->num_fields; ++i) {
4110                         MonoReflectionFieldBuilder* fb;
4111                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4112                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4113                                 return FALSE;
4114                 }
4115         }
4116         if (tb->events) {
4117                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4118                         MonoReflectionEventBuilder* eb;
4119                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4120                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4121                                 return FALSE;
4122                 }
4123         }
4124         if (tb->properties) {
4125                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4126                         MonoReflectionPropertyBuilder* pb;
4127                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4128                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4129                                 return FALSE;
4130                 }
4131         }
4132         if (tb->ctors) {
4133                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4134                         MonoReflectionCtorBuilder* cb;
4135                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4136                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4137                             !params_add_cattrs (assembly, cb->pinfo, error))
4138                                 return FALSE;
4139                 }
4140         }
4141
4142         if (tb->methods) {
4143                 for (i = 0; i < tb->num_methods; ++i) {
4144                         MonoReflectionMethodBuilder* mb;
4145                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4146                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4147                             !params_add_cattrs (assembly, mb->pinfo, error))
4148                                 return FALSE;
4149                 }
4150         }
4151
4152         if (tb->subtypes) {
4153                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4154                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4155                                 return FALSE;
4156                 }
4157         }
4158
4159         return TRUE;
4160 }
4161
4162 static gboolean
4163 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4164 {
4165         int i;
4166         
4167         mono_error_init (error);
4168
4169         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4170                 return FALSE;
4171
4172         if (moduleb->global_methods) {
4173                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4174                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4175                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4176                             !params_add_cattrs (assembly, mb->pinfo, error))
4177                                 return FALSE;
4178                 }
4179         }
4180
4181         if (moduleb->global_fields) {
4182                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4183                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4184                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4185                                 return FALSE;
4186                 }
4187         }
4188         
4189         if (moduleb->types) {
4190                 for (i = 0; i < moduleb->num_types; ++i) {
4191                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4192                                 return FALSE;
4193                 }
4194         }
4195
4196         return TRUE;
4197 }
4198
4199 static void
4200 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4201 {
4202         MonoDynamicTable *table;
4203         guint32 *values;
4204         char blob_size [6];
4205         guchar hash [20];
4206         char *b = blob_size;
4207         char *dir, *path;
4208
4209         table = &assembly->tables [MONO_TABLE_FILE];
4210         table->rows++;
4211         alloc_table (table, table->rows);
4212         values = table->values + table->next_idx * MONO_FILE_SIZE;
4213         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4214         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4215         if (image_is_dynamic (module->image)) {
4216                 /* This depends on the fact that the main module is emitted last */
4217                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4218                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4219         } else {
4220                 dir = NULL;
4221                 path = g_strdup (module->image->name);
4222         }
4223         mono_sha1_get_digest_from_file (path, hash);
4224         g_free (dir);
4225         g_free (path);
4226         mono_metadata_encode_value (20, b, &b);
4227         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4228         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4229         table->next_idx ++;
4230 }
4231
4232 static void
4233 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4234 {
4235         MonoDynamicTable *table;
4236         int i;
4237
4238         table = &assembly->tables [MONO_TABLE_MODULE];
4239         mb->table_idx = table->next_idx ++;
4240         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4241         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4242         i /= 16;
4243         ++i;
4244         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4245         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4246         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4247         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4248 }
4249
4250 static guint32
4251 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4252         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4253 {
4254         MonoDynamicTable *table;
4255         guint32 *values;
4256         guint32 visib, res;
4257
4258         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4259         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4260                 return 0;
4261
4262         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4263         table->rows++;
4264         alloc_table (table, table->rows);
4265         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4266
4267         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4268         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4269         if (klass->nested_in)
4270                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4271         else
4272                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4273         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4274         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4275
4276         res = table->next_idx;
4277
4278         table->next_idx ++;
4279
4280         /* Emit nested types */
4281         if (klass->ext && klass->ext->nested_classes) {
4282                 GList *tmp;
4283
4284                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4285                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4286         }
4287
4288         return res;
4289 }
4290
4291 static void
4292 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4293         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4294 {
4295         MonoError error;
4296         MonoClass *klass;
4297         guint32 idx, i;
4298
4299         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4300         mono_error_raise_exception (&error); /* FIXME don't raise here */
4301
4302         klass = mono_class_from_mono_type (t);
4303
4304         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4305
4306         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4307                                                                                                    parent_index, assembly);
4308
4309         /* 
4310          * Emit nested types
4311          * We need to do this ourselves since klass->nested_classes is not set up.
4312          */
4313         if (tb->subtypes) {
4314                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4315                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4316         }
4317 }
4318
4319 static void
4320 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4321         guint32 module_index, MonoDynamicImage *assembly)
4322 {
4323         MonoImage *image = module->image;
4324         MonoTableInfo  *t;
4325         guint32 i;
4326
4327         t = &image->tables [MONO_TABLE_TYPEDEF];
4328
4329         for (i = 0; i < t->rows; ++i) {
4330                 MonoError error;
4331                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4332                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4333
4334                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4335                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4336         }
4337 }
4338
4339 static void
4340 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4341 {
4342         MonoDynamicTable *table;
4343         guint32 *values;
4344         guint32 scope, scope_idx, impl, current_idx;
4345         gboolean forwarder = TRUE;
4346         gpointer iter = NULL;
4347         MonoClass *nested;
4348
4349         if (klass->nested_in) {
4350                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4351                 forwarder = FALSE;
4352         } else {
4353                 scope = resolution_scope_from_image (assembly, klass->image);
4354                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4355                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4356                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4357         }
4358
4359         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4360
4361         table->rows++;
4362         alloc_table (table, table->rows);
4363         current_idx = table->next_idx;
4364         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4365
4366         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4367         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4368         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4369         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4370         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4371
4372         table->next_idx++;
4373
4374         while ((nested = mono_class_get_nested_types (klass, &iter)))
4375                 add_exported_type (assemblyb, assembly, nested, current_idx);
4376 }
4377
4378 static void
4379 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4380 {
4381         MonoError error;
4382         MonoClass *klass;
4383         int i;
4384
4385         if (!assemblyb->type_forwarders)
4386                 return;
4387
4388         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4389                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4390                 MonoType *type;
4391                 if (!t)
4392                         continue;
4393
4394                 type = mono_reflection_type_get_handle (t, &error);
4395                 mono_error_assert_ok (&error);
4396                 g_assert (type);
4397
4398                 klass = mono_class_from_mono_type (type);
4399
4400                 add_exported_type (assemblyb, assembly, klass, 0);
4401         }
4402 }
4403
4404 #define align_pointer(base,p)\
4405         do {\
4406                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4407                 if (__diff & 3)\
4408                         (p) += 4 - (__diff & 3);\
4409         } while (0)
4410
4411 static int
4412 compare_constants (const void *a, const void *b)
4413 {
4414         const guint32 *a_values = (const guint32 *)a;
4415         const guint32 *b_values = (const guint32 *)b;
4416         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4417 }
4418
4419 static int
4420 compare_semantics (const void *a, const void *b)
4421 {
4422         const guint32 *a_values = (const guint32 *)a;
4423         const guint32 *b_values = (const guint32 *)b;
4424         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4425         if (assoc)
4426                 return assoc;
4427         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4428 }
4429
4430 static int
4431 compare_custom_attrs (const void *a, const void *b)
4432 {
4433         const guint32 *a_values = (const guint32 *)a;
4434         const guint32 *b_values = (const guint32 *)b;
4435
4436         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4437 }
4438
4439 static int
4440 compare_field_marshal (const void *a, const void *b)
4441 {
4442         const guint32 *a_values = (const guint32 *)a;
4443         const guint32 *b_values = (const guint32 *)b;
4444
4445         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4446 }
4447
4448 static int
4449 compare_nested (const void *a, const void *b)
4450 {
4451         const guint32 *a_values = (const guint32 *)a;
4452         const guint32 *b_values = (const guint32 *)b;
4453
4454         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4455 }
4456
4457 static int
4458 compare_genericparam (const void *a, const void *b)
4459 {
4460         MonoError error;
4461         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4462         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4463
4464         if ((*b_entry)->owner == (*a_entry)->owner) {
4465                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4466                 mono_error_assert_ok (&error);
4467                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4468                 mono_error_assert_ok (&error);
4469                 return 
4470                         mono_type_get_generic_param_num (a_type) -
4471                         mono_type_get_generic_param_num (b_type);
4472         } else
4473                 return (*a_entry)->owner - (*b_entry)->owner;
4474 }
4475
4476 static int
4477 compare_declsecurity_attrs (const void *a, const void *b)
4478 {
4479         const guint32 *a_values = (const guint32 *)a;
4480         const guint32 *b_values = (const guint32 *)b;
4481
4482         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4483 }
4484
4485 static int
4486 compare_interface_impl (const void *a, const void *b)
4487 {
4488         const guint32 *a_values = (const guint32 *)a;
4489         const guint32 *b_values = (const guint32 *)b;
4490
4491         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4492         if (klass)
4493                 return klass;
4494
4495         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4496 }
4497
4498 static void
4499 pad_heap (MonoDynamicStream *sh)
4500 {
4501         if (sh->index & 3) {
4502                 int sz = 4 - (sh->index & 3);
4503                 memset (sh->data + sh->index, 0, sz);
4504                 sh->index += sz;
4505         }
4506 }
4507
4508 struct StreamDesc {
4509         const char *name;
4510         MonoDynamicStream *stream;
4511 };
4512
4513 /*
4514  * build_compressed_metadata() fills in the blob of data that represents the 
4515  * raw metadata as it will be saved in the PE file. The five streams are output 
4516  * and the metadata tables are comnpressed from the guint32 array representation, 
4517  * to the compressed on-disk format.
4518  */
4519 static gboolean
4520 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4521 {
4522         MonoDynamicTable *table;
4523         int i;
4524         guint64 valid_mask = 0;
4525         guint64 sorted_mask;
4526         guint32 heapt_size = 0;
4527         guint32 meta_size = 256; /* allow for header and other stuff */
4528         guint32 table_offset;
4529         guint32 ntables = 0;
4530         guint64 *int64val;
4531         guint32 *int32val;
4532         guint16 *int16val;
4533         MonoImage *meta;
4534         unsigned char *p;
4535         struct StreamDesc stream_desc [5];
4536
4537         mono_error_init (error);
4538
4539         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4540         for (i = 0; i < assembly->gen_params->len; i++) {
4541                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4542                 if (!write_generic_param_entry (assembly, entry, error))
4543                         return FALSE;
4544         }
4545
4546         stream_desc [0].name  = "#~";
4547         stream_desc [0].stream = &assembly->tstream;
4548         stream_desc [1].name  = "#Strings";
4549         stream_desc [1].stream = &assembly->sheap;
4550         stream_desc [2].name  = "#US";
4551         stream_desc [2].stream = &assembly->us;
4552         stream_desc [3].name  = "#Blob";
4553         stream_desc [3].stream = &assembly->blob;
4554         stream_desc [4].name  = "#GUID";
4555         stream_desc [4].stream = &assembly->guid;
4556         
4557         /* tables that are sorted */
4558         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4559                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4560                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4561                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4562                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4563                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4564                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4565         
4566         /* Compute table sizes */
4567         /* the MonoImage has already been created in mono_image_basic_init() */
4568         meta = &assembly->image;
4569
4570         /* sizes should be multiple of 4 */
4571         pad_heap (&assembly->blob);
4572         pad_heap (&assembly->guid);
4573         pad_heap (&assembly->sheap);
4574         pad_heap (&assembly->us);
4575
4576         /* Setup the info used by compute_sizes () */
4577         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4578         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4579         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4580
4581         meta_size += assembly->blob.index;
4582         meta_size += assembly->guid.index;
4583         meta_size += assembly->sheap.index;
4584         meta_size += assembly->us.index;
4585
4586         for (i=0; i < MONO_TABLE_NUM; ++i)
4587                 meta->tables [i].rows = assembly->tables [i].rows;
4588         
4589         for (i = 0; i < MONO_TABLE_NUM; i++){
4590                 if (meta->tables [i].rows == 0)
4591                         continue;
4592                 valid_mask |= (guint64)1 << i;
4593                 ntables ++;
4594                 meta->tables [i].row_size = mono_metadata_compute_size (
4595                         meta, i, &meta->tables [i].size_bitfield);
4596                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4597         }
4598         heapt_size += 24; /* #~ header size */
4599         heapt_size += ntables * 4;
4600         /* make multiple of 4 */
4601         heapt_size += 3;
4602         heapt_size &= ~3;
4603         meta_size += heapt_size;
4604         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4605         p = (unsigned char*)meta->raw_metadata;
4606         /* the metadata signature */
4607         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4608         /* version numbers and 4 bytes reserved */
4609         int16val = (guint16*)p;
4610         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4611         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4612         p += 8;
4613         /* version string */
4614         int32val = (guint32*)p;
4615         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4616         p += 4;
4617         memcpy (p, meta->version, strlen (meta->version));
4618         p += GUINT32_FROM_LE (*int32val);
4619         align_pointer (meta->raw_metadata, p);
4620         int16val = (guint16*)p;
4621         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4622         *int16val = GUINT16_TO_LE (5); /* number of streams */
4623         p += 4;
4624
4625         /*
4626          * write the stream info.
4627          */
4628         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4629         table_offset += 3; table_offset &= ~3;
4630
4631         assembly->tstream.index = heapt_size;
4632         for (i = 0; i < 5; ++i) {
4633                 int32val = (guint32*)p;
4634                 stream_desc [i].stream->offset = table_offset;
4635                 *int32val++ = GUINT32_TO_LE (table_offset);
4636                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4637                 table_offset += GUINT32_FROM_LE (*int32val);
4638                 table_offset += 3; table_offset &= ~3;
4639                 p += 8;
4640                 strcpy ((char*)p, stream_desc [i].name);
4641                 p += strlen (stream_desc [i].name) + 1;
4642                 align_pointer (meta->raw_metadata, p);
4643         }
4644         /* 
4645          * now copy the data, the table stream header and contents goes first.
4646          */
4647         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4648         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4649         int32val = (guint32*)p;
4650         *int32val = GUINT32_TO_LE (0); /* reserved */
4651         p += 4;
4652
4653         *p++ = 2; /* version */
4654         *p++ = 0;
4655
4656         if (meta->idx_string_wide)
4657                 *p |= 0x01;
4658         if (meta->idx_guid_wide)
4659                 *p |= 0x02;
4660         if (meta->idx_blob_wide)
4661                 *p |= 0x04;
4662         ++p;
4663         *p++ = 1; /* reserved */
4664         int64val = (guint64*)p;
4665         *int64val++ = GUINT64_TO_LE (valid_mask);
4666         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4667         p += 16;
4668         int32val = (guint32*)p;
4669         for (i = 0; i < MONO_TABLE_NUM; i++){
4670                 if (meta->tables [i].rows == 0)
4671                         continue;
4672                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4673         }
4674         p = (unsigned char*)int32val;
4675
4676         /* sort the tables that still need sorting */
4677         table = &assembly->tables [MONO_TABLE_CONSTANT];
4678         if (table->rows)
4679                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4680         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4681         if (table->rows)
4682                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4683         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4684         if (table->rows)
4685                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4686         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4687         if (table->rows)
4688                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4689         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4690         if (table->rows)
4691                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4692         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4693         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4694         if (table->rows)
4695                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4696         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4697         if (table->rows)
4698                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4699
4700         /* compress the tables */
4701         for (i = 0; i < MONO_TABLE_NUM; i++){
4702                 int row, col;
4703                 guint32 *values;
4704                 guint32 bitfield = meta->tables [i].size_bitfield;
4705                 if (!meta->tables [i].rows)
4706                         continue;
4707                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4708                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4709                 meta->tables [i].base = (char*)p;
4710                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4711                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4712                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4713                                 switch (mono_metadata_table_size (bitfield, col)) {
4714                                 case 1:
4715                                         *p++ = values [col];
4716                                         break;
4717                                 case 2:
4718                                         *p++ = values [col] & 0xff;
4719                                         *p++ = (values [col] >> 8) & 0xff;
4720                                         break;
4721                                 case 4:
4722                                         *p++ = values [col] & 0xff;
4723                                         *p++ = (values [col] >> 8) & 0xff;
4724                                         *p++ = (values [col] >> 16) & 0xff;
4725                                         *p++ = (values [col] >> 24) & 0xff;
4726                                         break;
4727                                 default:
4728                                         g_assert_not_reached ();
4729                                 }
4730                         }
4731                 }
4732                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4733         }
4734         
4735         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4736         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4737         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4738         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4739         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4740
4741         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4742
4743         return TRUE;
4744 }
4745
4746 /*
4747  * Some tables in metadata need to be sorted according to some criteria, but
4748  * when methods and fields are first created with reflection, they may be assigned a token
4749  * that doesn't correspond to the final token they will get assigned after the sorting.
4750  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4751  * with the reflection objects that represent them. Once all the tables are set up, the 
4752  * reflection objects will contains the correct table index. fixup_method() will fixup the
4753  * tokens for the method with ILGenerator @ilgen.
4754  */
4755 static void
4756 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4757 {
4758         guint32 code_idx = GPOINTER_TO_UINT (value);
4759         MonoReflectionILTokenInfo *iltoken;
4760         MonoReflectionFieldBuilder *field;
4761         MonoReflectionCtorBuilder *ctor;
4762         MonoReflectionMethodBuilder *method;
4763         MonoReflectionTypeBuilder *tb;
4764         MonoReflectionArrayMethod *am;
4765         guint32 i, idx = 0;
4766         unsigned char *target;
4767
4768         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4769                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4770                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4771                 switch (target [3]) {
4772                 case MONO_TABLE_FIELD:
4773                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4774                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4775                                 idx = field->table_idx;
4776                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4777                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4778                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4779                         } else {
4780                                 g_assert_not_reached ();
4781                         }
4782                         break;
4783                 case MONO_TABLE_METHOD:
4784                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4785                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4786                                 idx = method->table_idx;
4787                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4788                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4789                                 idx = ctor->table_idx;
4790                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4791                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4792                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4793                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4794                         } else {
4795                                 g_assert_not_reached ();
4796                         }
4797                         break;
4798                 case MONO_TABLE_TYPEDEF:
4799                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4800                                 g_assert_not_reached ();
4801                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4802                         idx = tb->table_idx;
4803                         break;
4804                 case MONO_TABLE_MEMBERREF:
4805                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4806                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4807                                 idx = am->table_idx;
4808                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4809                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4810                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4811                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4812                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4813                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4814                                 continue;
4815                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4816                                 continue;
4817                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4818                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4819                                 g_assert (is_field_on_inst (f));
4820                                 continue;
4821                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4822                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4823                                 continue;
4824                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4825                                 continue;
4826                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4827                                 continue;
4828                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4829                                 continue;
4830                         } else {
4831                                 g_assert_not_reached ();
4832                         }
4833                         break;
4834                 case MONO_TABLE_METHODSPEC:
4835                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4836                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4837                                 g_assert (mono_method_signature (m)->generic_param_count);
4838                                 continue;
4839                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4840                                 continue;
4841                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4842                                 continue;
4843                         } else {
4844                                 g_assert_not_reached ();
4845                         }
4846                         break;
4847                 default:
4848                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4849                 }
4850                 target [0] = idx & 0xff;
4851                 target [1] = (idx >> 8) & 0xff;
4852                 target [2] = (idx >> 16) & 0xff;
4853         }
4854 }
4855
4856 /*
4857  * fixup_cattrs:
4858  *
4859  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4860  * value is not known when the table is emitted.
4861  */
4862 static void
4863 fixup_cattrs (MonoDynamicImage *assembly)
4864 {
4865         MonoDynamicTable *table;
4866         guint32 *values;
4867         guint32 type, i, idx, token;
4868         MonoObject *ctor;
4869
4870         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4871
4872         for (i = 0; i < table->rows; ++i) {
4873                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4874
4875                 type = values [MONO_CUSTOM_ATTR_TYPE];
4876                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4877                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4878                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4879                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4880                         g_assert (ctor);
4881
4882                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4883                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4884                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4885                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4886                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4887                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4888                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4889                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4890                         }
4891                 }
4892         }
4893 }
4894
4895 static void
4896 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4897 {
4898         MonoDynamicTable *table;
4899         guint32 *values;
4900
4901         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4902         table->rows++;
4903         alloc_table (table, table->rows);
4904         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4905         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4906         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4907         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4908         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4909         table->next_idx++;
4910 }
4911
4912 static void
4913 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4914 {
4915         MonoDynamicTable *table;
4916         guint32 *values;
4917         char blob_size [6];
4918         guchar hash [20];
4919         char *b = blob_size;
4920         char *name, *sname;
4921         guint32 idx, offset;
4922
4923         if (rsrc->filename) {
4924                 name = mono_string_to_utf8 (rsrc->filename);
4925                 sname = g_path_get_basename (name);
4926         
4927                 table = &assembly->tables [MONO_TABLE_FILE];
4928                 table->rows++;
4929                 alloc_table (table, table->rows);
4930                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4931                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4932                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4933                 g_free (sname);
4934
4935                 mono_sha1_get_digest_from_file (name, hash);
4936                 mono_metadata_encode_value (20, b, &b);
4937                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4938                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4939                 g_free (name);
4940                 idx = table->next_idx++;
4941                 rsrc->offset = 0;
4942                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4943         } else {
4944                 char sizebuf [4];
4945                 char *data;
4946                 guint len;
4947                 if (rsrc->data) {
4948                         data = mono_array_addr (rsrc->data, char, 0);
4949                         len = mono_array_length (rsrc->data);
4950                 } else {
4951                         data = NULL;
4952                         len = 0;
4953                 }
4954                 offset = len;
4955                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4956                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4957                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4958                 mono_image_add_stream_data (&assembly->resources, data, len);
4959
4960                 if (!mb->is_main)
4961                         /* 
4962                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4963                          * the main module, but that needs to reference the FILE table
4964                          * which isn't emitted yet.
4965                          */
4966                         return;
4967                 else
4968                         idx = 0;
4969         }
4970
4971         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4972 }
4973
4974 static void
4975 set_version_from_string (MonoString *version, guint32 *values)
4976 {
4977         gchar *ver, *p, *str;
4978         guint32 i;
4979         
4980         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4981         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4982         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4983         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4984         if (!version)
4985                 return;
4986         ver = str = mono_string_to_utf8 (version);
4987         for (i = 0; i < 4; ++i) {
4988                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4989                 switch (*p) {
4990                 case '.':
4991                         p++;
4992                         break;
4993                 case '*':
4994                         /* handle Revision and Build */
4995                         p++;
4996                         break;
4997                 }
4998                 ver = p;
4999         }
5000         g_free (str);
5001 }
5002
5003 static guint32
5004 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5005         gsize len;
5006         guint32 token = 0;
5007         char blob_size [6];
5008         char *b = blob_size;
5009
5010         if (!pkey)
5011                 return token;
5012
5013         len = mono_array_length (pkey);
5014         mono_metadata_encode_value (len, b, &b);
5015         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5016         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5017
5018         assembly->public_key = (guint8 *)g_malloc (len);
5019         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5020         assembly->public_key_len = len;
5021
5022         /* Special case: check for ECMA key (16 bytes) */
5023         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5024                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5025                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5026         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5027                 /* minimum key size (in 2.0) is 384 bits */
5028                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5029         } else {
5030                 /* FIXME - verifier */
5031                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5032                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5033         }
5034         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5035
5036         return token;
5037 }
5038
5039 static void
5040 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5041 {
5042         MonoDynamicTable *table;
5043         MonoDynamicImage *assembly;
5044         MonoReflectionAssemblyBuilder *assemblyb;
5045         MonoDomain *domain;
5046         guint32 *values;
5047         int i;
5048         guint32 module_index;
5049
5050         assemblyb = moduleb->assemblyb;
5051         assembly = moduleb->dynamic_image;
5052         domain = mono_object_domain (assemblyb);
5053
5054         /* Emit ASSEMBLY table */
5055         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5056         alloc_table (table, 1);
5057         values = table->values + MONO_ASSEMBLY_SIZE;
5058         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5059         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5060         if (assemblyb->culture) {
5061                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5062         } else {
5063                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5064         }
5065         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5066         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5067         set_version_from_string (assemblyb->version, values);
5068
5069         /* Emit FILE + EXPORTED_TYPE table */
5070         module_index = 0;
5071         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5072                 int j;
5073                 MonoReflectionModuleBuilder *file_module = 
5074                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5075                 if (file_module != moduleb) {
5076                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5077                         module_index ++;
5078                         if (file_module->types) {
5079                                 for (j = 0; j < file_module->num_types; ++j) {
5080                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5081                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5082                                 }
5083                         }
5084                 }
5085         }
5086         if (assemblyb->loaded_modules) {
5087                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5088                         MonoReflectionModule *file_module = 
5089                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5090                         mono_image_fill_file_table (domain, file_module, assembly);
5091                         module_index ++;
5092                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5093                 }
5094         }
5095         if (assemblyb->type_forwarders)
5096                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5097
5098         /* Emit MANIFESTRESOURCE table */
5099         module_index = 0;
5100         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5101                 int j;
5102                 MonoReflectionModuleBuilder *file_module = 
5103                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5104                 /* The table for the main module is emitted later */
5105                 if (file_module != moduleb) {
5106                         module_index ++;
5107                         if (file_module->resources) {
5108                                 int len = mono_array_length (file_module->resources);
5109                                 for (j = 0; j < len; ++j) {
5110                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5111                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5112                                 }
5113                         }
5114                 }
5115         }               
5116 }
5117
5118 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5119
5120 /*
5121  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5122  * for the modulebuilder @moduleb.
5123  * At the end of the process, method and field tokens are fixed up and the 
5124  * on-disk compressed metadata representation is created.
5125  * Return TRUE on success, or FALSE on failure and sets @error
5126  */
5127 gboolean
5128 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5129 {
5130         MonoDynamicTable *table;
5131         MonoDynamicImage *assembly;
5132         MonoReflectionAssemblyBuilder *assemblyb;
5133         MonoDomain *domain;
5134         MonoPtrArray types;
5135         guint32 *values;
5136         int i, j;
5137
5138         mono_error_init (error);
5139
5140         assemblyb = moduleb->assemblyb;
5141         assembly = moduleb->dynamic_image;
5142         domain = mono_object_domain (assemblyb);
5143
5144         if (assembly->text_rva)
5145                 return TRUE;
5146
5147         assembly->text_rva = START_TEXT_RVA;
5148
5149         if (moduleb->is_main) {
5150                 mono_image_emit_manifest (moduleb);
5151         }
5152
5153         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5154         table->rows = 1; /* .<Module> */
5155         table->next_idx++;
5156         alloc_table (table, table->rows);
5157         /*
5158          * Set the first entry.
5159          */
5160         values = table->values + table->columns;
5161         values [MONO_TYPEDEF_FLAGS] = 0;
5162         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5163         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5164         values [MONO_TYPEDEF_EXTENDS] = 0;
5165         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5166         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5167
5168         /* 
5169          * handle global methods 
5170          * FIXME: test what to do when global methods are defined in multiple modules.
5171          */
5172         if (moduleb->global_methods) {
5173                 table = &assembly->tables [MONO_TABLE_METHOD];
5174                 table->rows += mono_array_length (moduleb->global_methods);
5175                 alloc_table (table, table->rows);
5176                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5177                         if (!mono_image_get_method_info (
5178                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5179                                 goto leave;
5180                 }
5181         }
5182         if (moduleb->global_fields) {
5183                 table = &assembly->tables [MONO_TABLE_FIELD];
5184                 table->rows += mono_array_length (moduleb->global_fields);
5185                 alloc_table (table, table->rows);
5186                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5187                         mono_image_get_field_info (
5188                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5189                                 error);
5190                         if (!is_ok (error))
5191                                 goto leave;
5192                 }
5193         }
5194
5195         table = &assembly->tables [MONO_TABLE_MODULE];
5196         alloc_table (table, 1);
5197         mono_image_fill_module_table (domain, moduleb, assembly);
5198
5199         /* Collect all types into a list sorted by their table_idx */
5200         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5201
5202         if (moduleb->types)
5203                 for (i = 0; i < moduleb->num_types; ++i) {
5204                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5205                         collect_types (&types, type);
5206                 }
5207
5208         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5209         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5210         table->rows += mono_ptr_array_size (types);
5211         alloc_table (table, table->rows);
5212
5213         /*
5214          * Emit type names + namespaces at one place inside the string heap,
5215          * so load_class_names () needs to touch fewer pages.
5216          */
5217         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5218                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5219                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5220         }
5221         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5222                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5223                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5224         }
5225
5226         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5227                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5228                 if (!mono_image_get_type_info (domain, type, assembly, error))
5229                         goto leave_types;
5230         }
5231
5232         /* 
5233          * table->rows is already set above and in mono_image_fill_module_table.
5234          */
5235         /* add all the custom attributes at the end, once all the indexes are stable */
5236         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5237                 goto leave_types;
5238
5239         /* CAS assembly permissions */
5240         if (assemblyb->permissions_minimum)
5241                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5242         if (assemblyb->permissions_optional)
5243                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5244         if (assemblyb->permissions_refused)
5245                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5246
5247         if (!module_add_cattrs (assembly, moduleb, error))
5248                 goto leave_types;
5249
5250         /* fixup tokens */
5251         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5252
5253         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5254          * the final tokens and don't need another fixup pass. */
5255
5256         if (moduleb->global_methods) {
5257                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5258                         MonoReflectionMethodBuilder *mb = mono_array_get (
5259                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5260                         if (!mono_image_add_methodimpl (assembly, mb, error))
5261                                 goto leave_types;
5262                 }
5263         }
5264
5265         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5266                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5267                 if (type->methods) {
5268                         for (j = 0; j < type->num_methods; ++j) {
5269                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5270                                         type->methods, MonoReflectionMethodBuilder*, j);
5271
5272                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5273                                         goto leave_types;
5274                         }
5275                 }
5276         }
5277
5278         fixup_cattrs (assembly);
5279
5280 leave_types:
5281         mono_ptr_array_destroy (types);
5282 leave:
5283
5284         return mono_error_ok (error);
5285 }
5286
5287 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5288
5289 gboolean
5290 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5291 {
5292         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5293 }
5294
5295 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5296
5297
5298 typedef struct {
5299         guint32 import_lookup_table;
5300         guint32 timestamp;
5301         guint32 forwarder;
5302         guint32 name_rva;
5303         guint32 import_address_table_rva;
5304 } MonoIDT;
5305
5306 typedef struct {
5307         guint32 name_rva;
5308         guint32 flags;
5309 } MonoILT;
5310
5311 #ifndef DISABLE_REFLECTION_EMIT
5312
5313 /*
5314  * mono_image_insert_string:
5315  * @module: module builder object
5316  * @str: a string
5317  *
5318  * Insert @str into the user string stream of @module.
5319  */
5320 guint32
5321 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5322 {
5323         MonoDynamicImage *assembly;
5324         guint32 idx;
5325         char buf [16];
5326         char *b = buf;
5327         
5328         if (!module->dynamic_image)
5329                 mono_image_module_basic_init (module);
5330
5331         assembly = module->dynamic_image;
5332         
5333         if (assembly->save) {
5334                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5335                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5336 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5337         {
5338                 char *swapped = g_malloc (2 * mono_string_length (str));
5339                 const char *p = (const char*)mono_string_chars (str);
5340
5341                 swap_with_size (swapped, p, 2, mono_string_length (str));
5342                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5343                 g_free (swapped);
5344         }
5345 #else
5346                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5347 #endif
5348                 mono_image_add_stream_data (&assembly->us, "", 1);
5349         } else {
5350                 idx = assembly->us.index ++;
5351         }
5352
5353         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5354
5355         return MONO_TOKEN_STRING | idx;
5356 }
5357
5358 guint32
5359 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5360 {
5361         MonoClass *klass;
5362         guint32 token = 0;
5363         MonoMethodSignature *sig;
5364
5365         mono_error_init (error);
5366
5367         klass = obj->vtable->klass;
5368         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5369                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5370                 MonoMethodSignature *old;
5371                 guint32 sig_token, parent;
5372                 int nargs, i;
5373
5374                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5375
5376                 nargs = mono_array_length (opt_param_types);
5377                 old = mono_method_signature (method);
5378                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5379
5380                 sig->hasthis = old->hasthis;
5381                 sig->explicit_this = old->explicit_this;
5382                 sig->call_convention = old->call_convention;
5383                 sig->generic_param_count = old->generic_param_count;
5384                 sig->param_count = old->param_count + nargs;
5385                 sig->sentinelpos = old->param_count;
5386                 sig->ret = old->ret;
5387
5388                 for (i = 0; i < old->param_count; i++)
5389                         sig->params [i] = old->params [i];
5390
5391                 for (i = 0; i < nargs; i++) {
5392                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5393                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5394                         if (!is_ok (error)) goto fail;
5395                 }
5396
5397                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5398                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5399                 parent >>= MONO_TYPEDEFORREF_BITS;
5400
5401                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5402                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5403
5404                 sig_token = method_encode_signature (assembly, sig);
5405                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5406         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5407                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5408                 ReflectionMethodBuilder rmb;
5409                 guint32 parent, sig_token;
5410                 int nopt_args, nparams, ngparams, i;
5411
5412                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5413                         goto fail;
5414                 
5415                 rmb.opt_types = opt_param_types;
5416                 nopt_args = mono_array_length (opt_param_types);
5417
5418                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5419                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5420                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5421
5422                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5423                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5424                 sig->call_convention = rmb.call_conv;
5425                 sig->generic_param_count = ngparams;
5426                 sig->param_count = nparams + nopt_args;
5427                 sig->sentinelpos = nparams;
5428                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5429                 if (!is_ok (error)) goto fail;
5430
5431                 for (i = 0; i < nparams; i++) {
5432                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5433                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5434                         if (!is_ok (error)) goto fail;
5435                 }
5436
5437                 for (i = 0; i < nopt_args; i++) {
5438                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5439                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5440                         if (!is_ok (error)) goto fail;
5441                 }
5442
5443                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5444                 if (!is_ok (error))
5445                         goto fail;
5446
5447                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5448                 if (!mono_error_ok (error))
5449                         goto fail;
5450                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5451
5452                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5453                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5454
5455                 char *name = mono_string_to_utf8 (rmb.name);
5456                 token = mono_image_get_varargs_method_token (
5457                         assembly, parent, name, sig_token);
5458                 g_free (name);
5459         } else {
5460                 g_error ("requested method token for %s\n", klass->name);
5461         }
5462
5463         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5464         register_dyn_token (assembly, token, obj);
5465         return token;
5466 fail:
5467         g_assert (!mono_error_ok (error));
5468         return 0;
5469 }
5470
5471 /*
5472  * mono_image_create_token:
5473  * @assembly: a dynamic assembly
5474  * @obj:
5475  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5476  *
5477  * Get a token to insert in the IL code stream for the given MemberInfo.
5478  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5479  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5480  * entry.
5481  */
5482 guint32
5483 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5484                          gboolean create_open_instance, gboolean register_token,
5485                          MonoError *error)
5486 {
5487         MonoClass *klass;
5488         guint32 token = 0;
5489
5490         mono_error_init (error);
5491
5492         klass = obj->vtable->klass;
5493
5494         /* Check for user defined reflection objects */
5495         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5496         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5497                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5498                 return 0;
5499         }
5500
5501         if (strcmp (klass->name, "MethodBuilder") == 0) {
5502                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5503                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5504
5505                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5506                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5507                 else {
5508                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5509                         if (!mono_error_ok (error))
5510                                 return 0;
5511                 }
5512                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5513         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5514                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5515                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5516
5517                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5518                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5519                 else {
5520                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5521                         if (!mono_error_ok (error))
5522                                 return 0;
5523                 }
5524                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5525         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5526                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5527                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5528                 if (tb->generic_params) {
5529                         token = mono_image_get_generic_field_token (assembly, fb);
5530                 } else {
5531                         if (tb->module->dynamic_image == assembly) {
5532                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5533                         } else {
5534                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5535                         }
5536                 }
5537         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5538                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5539                 if (create_open_instance && tb->generic_params) {
5540                         MonoType *type;
5541                         init_type_builder_generics (obj);
5542                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5543                         return_val_if_nok (error, 0);
5544                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5545                         token = mono_metadata_token_from_dor (token);
5546                 } else if (tb->module->dynamic_image == assembly) {
5547                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5548                 } else {
5549                         MonoType *type;
5550                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5551                         return_val_if_nok (error, 0);
5552                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5553                 }
5554         } else if (strcmp (klass->name, "MonoType") == 0) {
5555                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5556                 return_val_if_nok (error, 0);
5557                 MonoClass *mc = mono_class_from_mono_type (type);
5558                 token = mono_metadata_token_from_dor (
5559                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5560         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5561                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5562                 return_val_if_nok (error, 0);
5563                 token = mono_metadata_token_from_dor (
5564                         mono_image_typedef_or_ref (assembly, type));
5565         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5566                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5567                 return_val_if_nok (error, 0);
5568                 token = mono_metadata_token_from_dor (
5569                         mono_image_typedef_or_ref (assembly, type));
5570         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5571                    strcmp (klass->name, "MonoMethod") == 0 ||
5572                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5573                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5574                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5575                 if (m->method->is_inflated) {
5576                         if (create_open_instance)
5577                                 token = mono_image_get_methodspec_token (assembly, m->method);
5578                         else
5579                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5580                 } else if ((m->method->klass->image == &assembly->image) &&
5581                          !m->method->klass->generic_class) {
5582                         static guint32 method_table_idx = 0xffffff;
5583                         if (m->method->klass->wastypebuilder) {
5584                                 /* we use the same token as the one that was assigned
5585                                  * to the Methodbuilder.
5586                                  * FIXME: do the equivalent for Fields.
5587                                  */
5588                                 token = m->method->token;
5589                         } else {
5590                                 /*
5591                                  * Each token should have a unique index, but the indexes are
5592                                  * assigned by managed code, so we don't know about them. An
5593                                  * easy solution is to count backwards...
5594                                  */
5595                                 method_table_idx --;
5596                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5597                         }
5598                 } else {
5599                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5600                 }
5601                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5602         } else if (strcmp (klass->name, "MonoField") == 0) {
5603                 MonoReflectionField *f = (MonoReflectionField *)obj;
5604                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5605                         static guint32 field_table_idx = 0xffffff;
5606                         field_table_idx --;
5607                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5608                 } else {
5609                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5610                 }
5611                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5612         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5613                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5614                 token = mono_image_get_array_token (assembly, m);
5615         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5616                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5617                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5618         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5619                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5620                 return_val_if_nok (error, 0);
5621                 token = mono_metadata_token_from_dor (
5622                         mono_image_typedef_or_ref (assembly, type));
5623         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5624                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5625                 token = mono_image_get_field_on_inst_token (assembly, f);
5626         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5627                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5628                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5629                 if (!mono_error_ok (error))
5630                         return 0;
5631         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5632                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5633                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5634                 if (!mono_error_ok (error))
5635                         return 0;
5636         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5637                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5638                 return_val_if_nok (error, 0);
5639                 token = mono_metadata_token_from_dor (
5640                                 mono_image_typedef_or_ref (assembly, type));
5641         } else {
5642                 g_error ("requested token for %s\n", klass->name);
5643         }
5644
5645         if (register_token)
5646                 mono_image_register_token (assembly, token, obj);
5647
5648         return token;
5649 }
5650
5651 /*
5652  * mono_image_register_token:
5653  *
5654  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5655  * the Module.ResolveXXXToken () methods to work.
5656  */
5657 void
5658 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5659 {
5660         MonoObject *prev;
5661
5662         dynamic_image_lock (assembly);
5663         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5664         if (prev) {
5665                 /* There could be multiple MethodInfo objects with the same token */
5666                 //g_assert (prev == obj);
5667         } else {
5668                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5669         }
5670         dynamic_image_unlock (assembly);
5671 }
5672
5673 static MonoDynamicImage*
5674 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5675 {
5676         static const guchar entrycode [16] = {0xff, 0x25, 0};
5677         MonoDynamicImage *image;
5678         int i;
5679
5680         const char *version;
5681
5682         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5683                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5684         else
5685                 version = mono_get_runtime_info ()->runtime_version;
5686
5687 #if HAVE_BOEHM_GC
5688         /* The MonoGHashTable's need GC tracking */
5689         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5690 #else
5691         image = g_new0 (MonoDynamicImage, 1);
5692 #endif
5693
5694         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5695         
5696         /*g_print ("created image %p\n", image);*/
5697         /* keep in sync with image.c */
5698         image->image.name = assembly_name;
5699         image->image.assembly_name = image->image.name; /* they may be different */
5700         image->image.module_name = module_name;
5701         image->image.version = g_strdup (version);
5702         image->image.md_version_major = 1;
5703         image->image.md_version_minor = 1;
5704         image->image.dynamic = TRUE;
5705
5706         image->image.references = g_new0 (MonoAssembly*, 1);
5707         image->image.references [0] = NULL;
5708
5709         mono_image_init (&image->image);
5710
5711         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");
5712         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5713         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5714         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5715         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5716         image->handleref = g_hash_table_new (NULL, NULL);
5717         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");
5718         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5719         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");
5720         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");
5721         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5722         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5723         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5724         image->gen_params = g_ptr_array_new ();
5725         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5726
5727         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5728         string_heap_init (&image->sheap);
5729         mono_image_add_stream_data (&image->us, "", 1);
5730         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5731         /* import tables... */
5732         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5733         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5734         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5735         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5736         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5737         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5738         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5739         stream_data_align (&image->code);
5740
5741         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5742
5743         for (i=0; i < MONO_TABLE_NUM; ++i) {
5744                 image->tables [i].next_idx = 1;
5745                 image->tables [i].columns = table_sizes [i];
5746         }
5747
5748         image->image.assembly = (MonoAssembly*)assembly;
5749         image->run = assembly->run;
5750         image->save = assembly->save;
5751         image->pe_kind = 0x1; /* ILOnly */
5752         image->machine = 0x14c; /* I386 */
5753         
5754         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5755
5756         dynamic_images_lock ();
5757
5758         if (!dynamic_images)
5759                 dynamic_images = g_ptr_array_new ();
5760
5761         g_ptr_array_add (dynamic_images, image);
5762
5763         dynamic_images_unlock ();
5764
5765         return image;
5766 }
5767 #endif
5768
5769 static void
5770 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5771 {
5772         g_free (key);
5773 }
5774
5775 static void
5776 release_hashtable (MonoGHashTable **hash)
5777 {
5778         if (*hash) {
5779                 mono_g_hash_table_destroy (*hash);
5780                 *hash = NULL;
5781         }
5782 }
5783
5784 void
5785 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5786 {
5787         release_hashtable (&image->token_fixups);
5788         release_hashtable (&image->handleref_managed);
5789         release_hashtable (&image->tokens);
5790         release_hashtable (&image->remapped_tokens);
5791         release_hashtable (&image->generic_def_objects);
5792         release_hashtable (&image->methodspec);
5793 }
5794
5795 // Free dynamic image pass one: Free resources but not image itself
5796 void
5797 mono_dynamic_image_free (MonoDynamicImage *image)
5798 {
5799         MonoDynamicImage *di = image;
5800         GList *list;
5801         int i;
5802
5803         if (di->methodspec)
5804                 mono_g_hash_table_destroy (di->methodspec);
5805         if (di->typespec)
5806                 g_hash_table_destroy (di->typespec);
5807         if (di->typeref)
5808                 g_hash_table_destroy (di->typeref);
5809         if (di->handleref)
5810                 g_hash_table_destroy (di->handleref);
5811         if (di->handleref_managed)
5812                 mono_g_hash_table_destroy (di->handleref_managed);
5813         if (di->tokens)
5814                 mono_g_hash_table_destroy (di->tokens);
5815         if (di->remapped_tokens)
5816                 mono_g_hash_table_destroy (di->remapped_tokens);
5817         if (di->generic_def_objects)
5818                 mono_g_hash_table_destroy (di->generic_def_objects);
5819         if (di->blob_cache) {
5820                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5821                 g_hash_table_destroy (di->blob_cache);
5822         }
5823         if (di->standalonesig_cache)
5824                 g_hash_table_destroy (di->standalonesig_cache);
5825         for (list = di->array_methods; list; list = list->next) {
5826                 ArrayMethod *am = (ArrayMethod *)list->data;
5827                 g_free (am->sig);
5828                 g_free (am->name);
5829                 g_free (am);
5830         }
5831         g_list_free (di->array_methods);
5832         if (di->gen_params) {
5833                 for (i = 0; i < di->gen_params->len; i++) {
5834                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5835                         mono_gc_deregister_root ((char*) &entry->gparam);
5836                         g_free (entry);
5837                 }
5838                 g_ptr_array_free (di->gen_params, TRUE);
5839         }
5840         if (di->token_fixups)
5841                 mono_g_hash_table_destroy (di->token_fixups);
5842         if (di->method_to_table_idx)
5843                 g_hash_table_destroy (di->method_to_table_idx);
5844         if (di->field_to_table_idx)
5845                 g_hash_table_destroy (di->field_to_table_idx);
5846         if (di->method_aux_hash)
5847                 g_hash_table_destroy (di->method_aux_hash);
5848         if (di->vararg_aux_hash)
5849                 g_hash_table_destroy (di->vararg_aux_hash);
5850         g_free (di->strong_name);
5851         g_free (di->win32_res);
5852         if (di->public_key)
5853                 g_free (di->public_key);
5854
5855         /*g_print ("string heap destroy for image %p\n", di);*/
5856         mono_dynamic_stream_reset (&di->sheap);
5857         mono_dynamic_stream_reset (&di->code);
5858         mono_dynamic_stream_reset (&di->resources);
5859         mono_dynamic_stream_reset (&di->us);
5860         mono_dynamic_stream_reset (&di->blob);
5861         mono_dynamic_stream_reset (&di->tstream);
5862         mono_dynamic_stream_reset (&di->guid);
5863         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5864                 g_free (di->tables [i].values);
5865         }
5866
5867         dynamic_images_lock ();
5868
5869         if (dynamic_images)
5870                 g_ptr_array_remove (dynamic_images, di);
5871
5872         dynamic_images_unlock ();
5873 }
5874
5875 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5876 void
5877 mono_dynamic_image_free_image (MonoDynamicImage *image)
5878 {
5879         /* See create_dynamic_mono_image () */
5880 #if HAVE_BOEHM_GC
5881         /* Allocated using GC_MALLOC */
5882 #else
5883         g_free (image);
5884 #endif
5885 }
5886
5887 #ifndef DISABLE_REFLECTION_EMIT
5888
5889 /*
5890  * mono_image_basic_init:
5891  * @assembly: an assembly builder object
5892  *
5893  * Create the MonoImage that represents the assembly builder and setup some
5894  * of the helper hash table and the basic metadata streams.
5895  */
5896 void
5897 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5898 {
5899         MonoDynamicAssembly *assembly;
5900         MonoDynamicImage *image;
5901         MonoDomain *domain = mono_object_domain (assemblyb);
5902         
5903         if (assemblyb->dynamic_assembly)
5904                 return;
5905
5906 #if HAVE_BOEHM_GC
5907         /* assembly->assembly.image might be GC allocated */
5908         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5909 #else
5910         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5911 #endif
5912
5913         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5914         
5915         assembly->assembly.ref_count = 1;
5916         assembly->assembly.dynamic = TRUE;
5917         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5918         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5919         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5920         if (assemblyb->culture)
5921                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5922         else
5923                 assembly->assembly.aname.culture = g_strdup ("");
5924
5925         if (assemblyb->version) {
5926                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5927                         char **version = g_strsplit (vstr, ".", 4);
5928                         char **parts = version;
5929                         assembly->assembly.aname.major = atoi (*parts++);
5930                         assembly->assembly.aname.minor = atoi (*parts++);
5931                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5932                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5933
5934                         g_strfreev (version);
5935                         g_free (vstr);
5936         } else {
5937                         assembly->assembly.aname.major = 0;
5938                         assembly->assembly.aname.minor = 0;
5939                         assembly->assembly.aname.build = 0;
5940                         assembly->assembly.aname.revision = 0;
5941         }
5942
5943         assembly->run = assemblyb->access != 2;
5944         assembly->save = assemblyb->access != 1;
5945         assembly->domain = domain;
5946
5947         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5948         image->initial_image = TRUE;
5949         assembly->assembly.aname.name = image->image.name;
5950         assembly->assembly.image = &image->image;
5951         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5952                 /* -1 to correct for the trailing NULL byte */
5953                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5954                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5955                 }
5956                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5957         }
5958
5959         mono_domain_assemblies_lock (domain);
5960         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5961         mono_domain_assemblies_unlock (domain);
5962
5963         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5964         
5965         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5966         
5967         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5968 }
5969
5970 #endif /* !DISABLE_REFLECTION_EMIT */
5971
5972 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5973
5974 static int
5975 calc_section_size (MonoDynamicImage *assembly)
5976 {
5977         int nsections = 0;
5978
5979         /* alignment constraints */
5980         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5981         g_assert ((assembly->code.index % 4) == 0);
5982         assembly->meta_size += 3;
5983         assembly->meta_size &= ~3;
5984         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5985         g_assert ((assembly->resources.index % 4) == 0);
5986
5987         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5988         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5989         nsections++;
5990
5991         if (assembly->win32_res) {
5992                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5993
5994                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5995                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5996                 nsections++;
5997         }
5998
5999         assembly->sections [MONO_SECTION_RELOC].size = 12;
6000         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6001         nsections++;
6002
6003         return nsections;
6004 }
6005
6006 typedef struct {
6007         guint32 id;
6008         guint32 offset;
6009         GSList *children;
6010         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6011 } ResTreeNode;
6012
6013 static int
6014 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6015 {
6016         ResTreeNode *t1 = (ResTreeNode*)a;
6017         ResTreeNode *t2 = (ResTreeNode*)b;
6018
6019         return t1->id - t2->id;
6020 }
6021
6022 /*
6023  * resource_tree_create:
6024  *
6025  *  Organize the resources into a resource tree.
6026  */
6027 static ResTreeNode *
6028 resource_tree_create (MonoArray *win32_resources)
6029 {
6030         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6031         GSList *l;
6032         int i;
6033
6034         tree = g_new0 (ResTreeNode, 1);
6035         
6036         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6037                 MonoReflectionWin32Resource *win32_res =
6038                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6039
6040                 /* Create node */
6041
6042                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6043                 lang_node = g_new0 (ResTreeNode, 1);
6044                 lang_node->id = win32_res->lang_id;
6045                 lang_node->win32_res = win32_res;
6046
6047                 /* Create type node if neccesary */
6048                 type_node = NULL;
6049                 for (l = tree->children; l; l = l->next)
6050                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6051                                 type_node = (ResTreeNode*)l->data;
6052                                 break;
6053                         }
6054
6055                 if (!type_node) {
6056                         type_node = g_new0 (ResTreeNode, 1);
6057                         type_node->id = win32_res->res_type;
6058
6059                         /* 
6060                          * The resource types have to be sorted otherwise
6061                          * Windows Explorer can't display the version information.
6062                          */
6063                         tree->children = g_slist_insert_sorted (tree->children, 
6064                                 type_node, resource_tree_compare_by_id);
6065                 }
6066
6067                 /* Create res node if neccesary */
6068                 res_node = NULL;
6069                 for (l = type_node->children; l; l = l->next)
6070                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6071                                 res_node = (ResTreeNode*)l->data;
6072                                 break;
6073                         }
6074
6075                 if (!res_node) {
6076                         res_node = g_new0 (ResTreeNode, 1);
6077                         res_node->id = win32_res->res_id;
6078                         type_node->children = g_slist_append (type_node->children, res_node);
6079                 }
6080
6081                 res_node->children = g_slist_append (res_node->children, lang_node);
6082         }
6083
6084         return tree;
6085 }
6086
6087 /*
6088  * resource_tree_encode:
6089  * 
6090  *   Encode the resource tree into the format used in the PE file.
6091  */
6092 static void
6093 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6094 {
6095         char *entries;
6096         MonoPEResourceDir dir;
6097         MonoPEResourceDirEntry dir_entry;
6098         MonoPEResourceDataEntry data_entry;
6099         GSList *l;
6100         guint32 res_id_entries;
6101
6102         /*
6103          * For the format of the resource directory, see the article
6104          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6105          * Matt Pietrek
6106          */
6107
6108         memset (&dir, 0, sizeof (dir));
6109         memset (&dir_entry, 0, sizeof (dir_entry));
6110         memset (&data_entry, 0, sizeof (data_entry));
6111
6112         g_assert (sizeof (dir) == 16);
6113         g_assert (sizeof (dir_entry) == 8);
6114         g_assert (sizeof (data_entry) == 16);
6115
6116         node->offset = p - begin;
6117
6118         /* IMAGE_RESOURCE_DIRECTORY */
6119         res_id_entries = g_slist_length (node->children);
6120         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6121
6122         memcpy (p, &dir, sizeof (dir));
6123         p += sizeof (dir);
6124
6125         /* Reserve space for entries */
6126         entries = p;
6127         p += sizeof (dir_entry) * res_id_entries;
6128
6129         /* Write children */
6130         for (l = node->children; l; l = l->next) {
6131                 ResTreeNode *child = (ResTreeNode*)l->data;
6132
6133                 if (child->win32_res) {
6134                         guint32 size;
6135
6136                         child->offset = p - begin;
6137
6138                         /* IMAGE_RESOURCE_DATA_ENTRY */
6139                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6140                         size = mono_array_length (child->win32_res->res_data);
6141                         data_entry.rde_size = GUINT32_TO_LE (size);
6142
6143                         memcpy (p, &data_entry, sizeof (data_entry));
6144                         p += sizeof (data_entry);
6145
6146                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6147                         p += size;
6148                 } else {
6149                         resource_tree_encode (child, begin, p, &p);
6150                 }
6151         }
6152
6153         /* IMAGE_RESOURCE_ENTRY */
6154         for (l = node->children; l; l = l->next) {
6155                 ResTreeNode *child = (ResTreeNode*)l->data;
6156
6157                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6158                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6159
6160                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6161                 entries += sizeof (dir_entry);
6162         }
6163
6164         *endbuf = p;
6165 }
6166
6167 static void
6168 resource_tree_free (ResTreeNode * node)
6169 {
6170         GSList * list;
6171         for (list = node->children; list; list = list->next)
6172                 resource_tree_free ((ResTreeNode*)list->data);
6173         g_slist_free(node->children);
6174         g_free (node);
6175 }
6176
6177 static void
6178 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6179 {
6180         char *buf;
6181         char *p;
6182         guint32 size, i;
6183         MonoReflectionWin32Resource *win32_res;
6184         ResTreeNode *tree;
6185
6186         if (!assemblyb->win32_resources)
6187                 return;
6188
6189         /*
6190          * Resources are stored in a three level tree inside the PE file.
6191          * - level one contains a node for each type of resource
6192          * - level two contains a node for each resource
6193          * - level three contains a node for each instance of a resource for a
6194          *   specific language.
6195          */
6196
6197         tree = resource_tree_create (assemblyb->win32_resources);
6198
6199         /* Estimate the size of the encoded tree */
6200         size = 0;
6201         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6202                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6203                 size += mono_array_length (win32_res->res_data);
6204         }
6205         /* Directory structure */
6206         size += mono_array_length (assemblyb->win32_resources) * 256;
6207         p = buf = (char *)g_malloc (size);
6208
6209         resource_tree_encode (tree, p, p, &p);
6210
6211         g_assert (p - buf <= size);
6212
6213         assembly->win32_res = (char *)g_malloc (p - buf);
6214         assembly->win32_res_size = p - buf;
6215         memcpy (assembly->win32_res, buf, p - buf);
6216
6217         g_free (buf);
6218         resource_tree_free (tree);
6219 }
6220
6221 static void
6222 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6223 {
6224         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6225         int i;
6226
6227         p += sizeof (MonoPEResourceDir);
6228         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6229                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6230                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6231                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6232                         fixup_resource_directory (res_section, child, rva);
6233                 } else {
6234                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6235                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6236                 }
6237
6238                 p += sizeof (MonoPEResourceDirEntry);
6239         }
6240 }
6241
6242 static void
6243 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6244 {
6245         guint32 dummy;
6246         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6247                 g_error ("WriteFile returned %d\n", GetLastError ());
6248 }
6249
6250 /*
6251  * mono_image_create_pefile:
6252  * @mb: a module builder object
6253  * 
6254  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6255  * assembly->pefile where it can be easily retrieved later in chunks.
6256  */
6257 gboolean
6258 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6259 {
6260         MonoMSDOSHeader *msdos;
6261         MonoDotNetHeader *header;
6262         MonoSectionTable *section;
6263         MonoCLIHeader *cli_header;
6264         guint32 size, image_size, virtual_base, text_offset;
6265         guint32 header_start, section_start, file_offset, virtual_offset;
6266         MonoDynamicImage *assembly;
6267         MonoReflectionAssemblyBuilder *assemblyb;
6268         MonoDynamicStream pefile_stream = {0};
6269         MonoDynamicStream *pefile = &pefile_stream;
6270         int i, nsections;
6271         guint32 *rva, value;
6272         guchar *p;
6273         static const unsigned char msheader[] = {
6274                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6275                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6276                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6277                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6278                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6279                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6280                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6281                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6282         };
6283
6284         mono_error_init (error);
6285
6286         assemblyb = mb->assemblyb;
6287
6288         mono_image_basic_init (assemblyb);
6289         assembly = mb->dynamic_image;
6290
6291         assembly->pe_kind = assemblyb->pe_kind;
6292         assembly->machine = assemblyb->machine;
6293         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6294         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6295         
6296         if (!mono_image_build_metadata (mb, error))
6297                 return FALSE;
6298         
6299
6300         if (mb->is_main && assemblyb->resources) {
6301                 int len = mono_array_length (assemblyb->resources);
6302                 for (i = 0; i < len; ++i)
6303                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6304         }
6305
6306         if (mb->resources) {
6307                 int len = mono_array_length (mb->resources);
6308                 for (i = 0; i < len; ++i)
6309                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6310         }
6311
6312         if (!build_compressed_metadata (assembly, error))
6313                 return FALSE;
6314
6315         if (mb->is_main)
6316                 assembly_add_win32_resources (assembly, assemblyb);
6317
6318         nsections = calc_section_size (assembly);
6319         
6320         /* The DOS header and stub */
6321         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6322         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6323
6324         /* the dotnet header */
6325         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6326
6327         /* the section tables */
6328         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6329
6330         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6331         virtual_offset = VIRT_ALIGN;
6332         image_size = 0;
6333
6334         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6335                 if (!assembly->sections [i].size)
6336                         continue;
6337                 /* align offsets */
6338                 file_offset += FILE_ALIGN - 1;
6339                 file_offset &= ~(FILE_ALIGN - 1);
6340                 virtual_offset += VIRT_ALIGN - 1;
6341                 virtual_offset &= ~(VIRT_ALIGN - 1);
6342
6343                 assembly->sections [i].offset = file_offset;
6344                 assembly->sections [i].rva = virtual_offset;
6345
6346                 file_offset += assembly->sections [i].size;
6347                 virtual_offset += assembly->sections [i].size;
6348                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6349         }
6350
6351         file_offset += FILE_ALIGN - 1;
6352         file_offset &= ~(FILE_ALIGN - 1);
6353
6354         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6355
6356         /* back-patch info */
6357         msdos = (MonoMSDOSHeader*)pefile->data;
6358         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6359
6360         header = (MonoDotNetHeader*)(pefile->data + header_start);
6361         header->pesig [0] = 'P';
6362         header->pesig [1] = 'E';
6363         
6364         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6365         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6366         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6367         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6368         if (assemblyb->pekind == 1) {
6369                 /* it's a dll */
6370                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6371         } else {
6372                 /* it's an exe */
6373                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6374         }
6375
6376         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6377
6378         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6379         header->pe.pe_major = 6;
6380         header->pe.pe_minor = 0;
6381         size = assembly->sections [MONO_SECTION_TEXT].size;
6382         size += FILE_ALIGN - 1;
6383         size &= ~(FILE_ALIGN - 1);
6384         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6385         size = assembly->sections [MONO_SECTION_RSRC].size;
6386         size += FILE_ALIGN - 1;
6387         size &= ~(FILE_ALIGN - 1);
6388         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6389         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6390         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6391         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6392         /* pe_rva_entry_point always at the beginning of the text section */
6393         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6394
6395         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6396         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6397         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6398         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6399         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6400         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6401         size = section_start;
6402         size += FILE_ALIGN - 1;
6403         size &= ~(FILE_ALIGN - 1);
6404         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6405         size = image_size;
6406         size += VIRT_ALIGN - 1;
6407         size &= ~(VIRT_ALIGN - 1);
6408         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6409
6410         /*
6411         // Translate the PEFileKind value to the value expected by the Windows loader
6412         */
6413         {
6414                 short kind;
6415
6416                 /*
6417                 // PEFileKinds.Dll == 1
6418                 // PEFileKinds.ConsoleApplication == 2
6419                 // PEFileKinds.WindowApplication == 3
6420                 //
6421                 // need to get:
6422                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6423                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6424                 */
6425                 if (assemblyb->pekind == 3)
6426                         kind = 2;
6427                 else
6428                         kind = 3;
6429                 
6430                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6431         }    
6432         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6433         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6434         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6435         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6436         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6437         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6438
6439         /* fill data directory entries */
6440
6441         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6442         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6443
6444         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6445         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6446
6447         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6448         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6449         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6450         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6451         /* patch entrypoint name */
6452         if (assemblyb->pekind == 1)
6453                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6454         else
6455                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6456         /* patch imported function RVA name */
6457         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6458         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6459
6460         /* the import table */
6461         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6462         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6463         /* patch imported dll RVA name and other entries in the dir */
6464         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6465         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6466         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6467         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6468         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6469         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6470
6471         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6472         value = (assembly->text_rva + assembly->imp_names_offset);
6473         *p++ = (value) & 0xff;
6474         *p++ = (value >> 8) & (0xff);
6475         *p++ = (value >> 16) & (0xff);
6476         *p++ = (value >> 24) & (0xff);
6477
6478         /* the CLI header info */
6479         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6480         cli_header->ch_size = GUINT32_FROM_LE (72);
6481         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6482         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6483         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6484         if (assemblyb->entry_point) {
6485                 guint32 table_idx = 0;
6486                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6487                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6488                         table_idx = methodb->table_idx;
6489                 } else {
6490                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6491                 }
6492                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6493         } else {
6494                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6495         }
6496         /* The embedded managed resources */
6497         text_offset = assembly->text_rva + assembly->code.index;
6498         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6499         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6500         text_offset += assembly->resources.index;
6501         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6502         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6503         text_offset += assembly->meta_size;
6504         if (assembly->strong_name_size) {
6505                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6506                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6507                 text_offset += assembly->strong_name_size;
6508         }
6509
6510         /* write the section tables and section content */
6511         section = (MonoSectionTable*)(pefile->data + section_start);
6512         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6513                 static const char section_names [][7] = {
6514                         ".text", ".rsrc", ".reloc"
6515                 };
6516                 if (!assembly->sections [i].size)
6517                         continue;
6518                 strcpy (section->st_name, section_names [i]);
6519                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6520                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6521                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6522                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6523                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6524                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6525                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6526                 section ++;
6527         }
6528         
6529         checked_write_file (file, pefile->data, pefile->index);
6530         
6531         mono_dynamic_stream_reset (pefile);
6532         
6533         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6534                 if (!assembly->sections [i].size)
6535                         continue;
6536                 
6537                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6538                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6539                 
6540                 switch (i) {
6541                 case MONO_SECTION_TEXT:
6542                         /* patch entry point */
6543                         p = (guchar*)(assembly->code.data + 2);
6544                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6545                         *p++ = (value) & 0xff;
6546                         *p++ = (value >> 8) & 0xff;
6547                         *p++ = (value >> 16) & 0xff;
6548                         *p++ = (value >> 24) & 0xff;
6549                 
6550                         checked_write_file (file, assembly->code.data, assembly->code.index);
6551                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6552                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6553                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6554                                 
6555
6556                         g_free (assembly->image.raw_metadata);
6557                         break;
6558                 case MONO_SECTION_RELOC: {
6559                         struct {
6560                                 guint32 page_rva;
6561                                 guint32 block_size;
6562                                 guint16 type_and_offset;
6563                                 guint16 term;
6564                         } reloc;
6565                         
6566                         g_assert (sizeof (reloc) == 12);
6567                         
6568                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6569                         reloc.block_size = GUINT32_FROM_LE (12);
6570                         
6571                         /* 
6572                          * the entrypoint is always at the start of the text section 
6573                          * 3 is IMAGE_REL_BASED_HIGHLOW
6574                          * 2 is patch_size_rva - text_rva
6575                          */
6576                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6577                         reloc.term = 0;
6578                         
6579                         checked_write_file (file, &reloc, sizeof (reloc));
6580                         
6581                         break;
6582                 }
6583                 case MONO_SECTION_RSRC:
6584                         if (assembly->win32_res) {
6585
6586                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6587                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6588                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6589                         }
6590                         break;
6591                 default:
6592                         g_assert_not_reached ();
6593                 }
6594         }
6595         
6596         /* check that the file is properly padded */
6597         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6598                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6599         if (! SetEndOfFile (file))
6600                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6601         
6602         mono_dynamic_stream_reset (&assembly->code);
6603         mono_dynamic_stream_reset (&assembly->us);
6604         mono_dynamic_stream_reset (&assembly->blob);
6605         mono_dynamic_stream_reset (&assembly->guid);
6606         mono_dynamic_stream_reset (&assembly->sheap);
6607
6608         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6609         g_hash_table_destroy (assembly->blob_cache);
6610         assembly->blob_cache = NULL;
6611
6612         return TRUE;
6613 }
6614
6615 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6616
6617 gboolean
6618 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6619 {
6620         g_assert_not_reached ();
6621 }
6622
6623 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6624
6625 #ifndef DISABLE_REFLECTION_EMIT
6626
6627 MonoReflectionModule *
6628 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6629 {
6630         MonoError error;
6631         MonoReflectionModule *result = NULL;
6632         char *name;
6633         MonoImage *image;
6634         MonoImageOpenStatus status;
6635         MonoDynamicAssembly *assembly;
6636         guint32 module_count;
6637         MonoImage **new_modules;
6638         gboolean *new_modules_loaded;
6639         
6640         name = mono_string_to_utf8 (fileName);
6641
6642         image = mono_image_open (name, &status);
6643         if (!image) {
6644                 MonoException *exc;
6645                 if (status == MONO_IMAGE_ERROR_ERRNO)
6646                         exc = mono_get_exception_file_not_found (fileName);
6647                 else
6648                         exc = mono_get_exception_bad_image_format (name);
6649                 g_free (name);
6650                 mono_raise_exception (exc);
6651         }
6652
6653         g_free (name);
6654
6655         assembly = ab->dynamic_assembly;
6656         image->assembly = (MonoAssembly*)assembly;
6657
6658         module_count = image->assembly->image->module_count;
6659         new_modules = g_new0 (MonoImage *, module_count + 1);
6660         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6661
6662         if (image->assembly->image->modules)
6663                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6664         if (image->assembly->image->modules_loaded)
6665                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6666         new_modules [module_count] = image;
6667         new_modules_loaded [module_count] = TRUE;
6668         mono_image_addref (image);
6669
6670         g_free (image->assembly->image->modules);
6671         image->assembly->image->modules = new_modules;
6672         image->assembly->image->modules_loaded = new_modules_loaded;
6673         image->assembly->image->module_count ++;
6674
6675         mono_assembly_load_references (image, &status);
6676         if (status) {
6677                 mono_image_close (image);
6678                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6679         }
6680
6681         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6682         mono_error_raise_exception (&error); /* FIXME don't raise here */
6683         return result;
6684 }
6685
6686 #endif /* DISABLE_REFLECTION_EMIT */
6687
6688 /*
6689  * We need to return always the same object for MethodInfo, FieldInfo etc..
6690  * but we need to consider the reflected type.
6691  * type uses a different hash, since it uses custom hash/equal functions.
6692  */
6693
6694 typedef struct {
6695         gpointer item;
6696         MonoClass *refclass;
6697 } ReflectedEntry;
6698
6699 static gboolean
6700 reflected_equal (gconstpointer a, gconstpointer b) {
6701         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6702         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6703
6704         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6705 }
6706
6707 static guint
6708 reflected_hash (gconstpointer a) {
6709         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6710         return mono_aligned_addr_hash (ea->item);
6711 }
6712
6713 #define CHECK_OBJECT(t,p,k)     \
6714         do {    \
6715                 t _obj; \
6716                 ReflectedEntry e;       \
6717                 e.item = (p);   \
6718                 e.refclass = (k);       \
6719                 mono_domain_lock (domain);      \
6720                 if (!domain->refobject_hash)    \
6721                         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");  \
6722                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6723                         mono_domain_unlock (domain);    \
6724                         return _obj;    \
6725                 }       \
6726         mono_domain_unlock (domain); \
6727         } while (0)
6728
6729 #ifdef HAVE_BOEHM_GC
6730 /* ReflectedEntry doesn't need to be GC tracked */
6731 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6732 #define FREE_REFENTRY(entry) g_free ((entry))
6733 #define REFENTRY_REQUIRES_CLEANUP
6734 #else
6735 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6736 /* FIXME: */
6737 #define FREE_REFENTRY(entry)
6738 #endif
6739
6740 #define CACHE_OBJECT(t,p,o,k)   \
6741         do {    \
6742                 t _obj; \
6743         ReflectedEntry pe; \
6744         pe.item = (p); \
6745         pe.refclass = (k); \
6746         mono_domain_lock (domain); \
6747                 if (!domain->refobject_hash)    \
6748                         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");  \
6749         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6750         if (!_obj) { \
6751                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6752                     e->item = (p);      \
6753                     e->refclass = (k);  \
6754                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6755             _obj = o; \
6756         } \
6757                 mono_domain_unlock (domain);    \
6758         return _obj; \
6759         } while (0)
6760
6761 static void
6762 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6763 {
6764         mono_domain_lock (domain);
6765         if (domain->refobject_hash) {
6766         ReflectedEntry pe;
6767                 gpointer orig_pe, orig_value;
6768
6769                 pe.item = o;
6770                 pe.refclass = klass;
6771                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6772                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6773                         FREE_REFENTRY (orig_pe);
6774                 }
6775         }
6776         mono_domain_unlock (domain);
6777 }
6778
6779 #ifdef REFENTRY_REQUIRES_CLEANUP
6780 static void
6781 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6782 {
6783         FREE_REFENTRY (key);
6784 }
6785 #endif
6786
6787 void
6788 mono_reflection_cleanup_domain (MonoDomain *domain)
6789 {
6790         if (domain->refobject_hash) {
6791 /*let's avoid scanning the whole hashtable if not needed*/
6792 #ifdef REFENTRY_REQUIRES_CLEANUP
6793                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6794 #endif
6795                 mono_g_hash_table_destroy (domain->refobject_hash);
6796                 domain->refobject_hash = NULL;
6797         }
6798 }
6799
6800 #ifndef DISABLE_REFLECTION_EMIT
6801 static gpointer
6802 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6803 {
6804         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6805 }
6806
6807 static gpointer
6808 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6809 {
6810         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6811 }
6812
6813 void
6814 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6815 {
6816         MonoDynamicImage *image = moduleb->dynamic_image;
6817         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6818         if (!image) {
6819                 MonoError error;
6820                 int module_count;
6821                 MonoImage **new_modules;
6822                 MonoImage *ass;
6823                 char *name, *fqname;
6824                 /*
6825                  * FIXME: we already created an image in mono_image_basic_init (), but
6826                  * we don't know which module it belongs to, since that is only 
6827                  * determined at assembly save time.
6828                  */
6829                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6830                 name = mono_string_to_utf8 (ab->name);
6831                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6832                 if (!mono_error_ok (&error)) {
6833                         g_free (name);
6834                         mono_error_raise_exception (&error);
6835                 }
6836                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6837
6838                 moduleb->module.image = &image->image;
6839                 moduleb->dynamic_image = image;
6840                 register_module (mono_object_domain (moduleb), moduleb, image);
6841
6842                 /* register the module with the assembly */
6843                 ass = ab->dynamic_assembly->assembly.image;
6844                 module_count = ass->module_count;
6845                 new_modules = g_new0 (MonoImage *, module_count + 1);
6846
6847                 if (ass->modules)
6848                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6849                 new_modules [module_count] = &image->image;
6850                 mono_image_addref (&image->image);
6851
6852                 g_free (ass->modules);
6853                 ass->modules = new_modules;
6854                 ass->module_count ++;
6855         }
6856 }
6857
6858 void
6859 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6860 {
6861         MonoDynamicImage *image = moduleb->dynamic_image;
6862
6863         g_assert (type->type);
6864         image->wrappers_type = mono_class_from_mono_type (type->type);
6865 }
6866
6867 #endif
6868
6869 /*
6870  * mono_assembly_get_object:
6871  * @domain: an app domain
6872  * @assembly: an assembly
6873  *
6874  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6875  */
6876 MonoReflectionAssembly*
6877 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6878 {
6879         MonoError error;
6880         MonoReflectionAssembly *result;
6881         result = mono_assembly_get_object_checked (domain, assembly, &error);
6882         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6883         return result;
6884 }
6885 /*
6886  * mono_assembly_get_object_checked:
6887  * @domain: an app domain
6888  * @assembly: an assembly
6889  *
6890  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6891  */
6892 MonoReflectionAssembly*
6893 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6894 {
6895         MonoReflectionAssembly *res;
6896         
6897         mono_error_init (error);
6898
6899         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6900         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6901         if (!res)
6902                 return NULL;
6903         res->assembly = assembly;
6904
6905         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6906 }
6907
6908
6909
6910 MonoReflectionModule*   
6911 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6912 {
6913         MonoError error;
6914         MonoReflectionModule *result;
6915         result = mono_module_get_object_checked (domain, image, &error);
6916         mono_error_raise_exception (&error);
6917         return result;
6918 }
6919
6920 MonoReflectionModule*
6921 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6922 {
6923         MonoReflectionModule *res;
6924         char* basename;
6925         
6926         mono_error_init (error);
6927         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6928         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6929         if (!res)
6930                 return NULL;
6931
6932         res->image = image;
6933         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6934         if (!assm_obj)
6935                 return NULL;
6936         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6937
6938         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6939         basename = g_path_get_basename (image->name);
6940         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6941         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6942         
6943         g_free (basename);
6944
6945         if (image->assembly->image == image) {
6946                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6947         } else {
6948                 int i;
6949                 res->token = 0;
6950                 if (image->assembly->image->modules) {
6951                         for (i = 0; i < image->assembly->image->module_count; i++) {
6952                                 if (image->assembly->image->modules [i] == image)
6953                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6954                         }
6955                         g_assert (res->token);
6956                 }
6957         }
6958
6959         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6960 }
6961
6962 MonoReflectionModule*
6963 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6964 {
6965         MonoError error;
6966         MonoReflectionModule *result;
6967         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6968         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6969         return result;
6970 }
6971
6972 MonoReflectionModule*
6973 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6974 {
6975         MonoReflectionModule *res;
6976         MonoTableInfo *table;
6977         guint32 cols [MONO_FILE_SIZE];
6978         const char *name;
6979         guint32 i, name_idx;
6980         const char *val;
6981         
6982         mono_error_init (error);
6983
6984         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6985         if (!res)
6986                 return NULL;
6987
6988         table = &image->tables [MONO_TABLE_FILE];
6989         g_assert (table_index < table->rows);
6990         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6991
6992         res->image = NULL;
6993         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6994         if (!assm_obj)
6995                 return NULL;
6996         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6997         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6998
6999         /* Check whenever the row has a corresponding row in the moduleref table */
7000         table = &image->tables [MONO_TABLE_MODULEREF];
7001         for (i = 0; i < table->rows; ++i) {
7002                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7003                 val = mono_metadata_string_heap (image, name_idx);
7004                 if (strcmp (val, name) == 0)
7005                         res->image = image->modules [i];
7006         }
7007
7008         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7009         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7010         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7011         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7012         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7013
7014         return res;
7015 }
7016
7017 static gboolean
7018 verify_safe_for_managed_space (MonoType *type)
7019 {
7020         switch (type->type) {
7021 #ifdef DEBUG_HARDER
7022         case MONO_TYPE_ARRAY:
7023                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7024         case MONO_TYPE_PTR:
7025                 return verify_safe_for_managed_space (type->data.type);
7026         case MONO_TYPE_SZARRAY:
7027                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7028         case MONO_TYPE_GENERICINST: {
7029                 MonoGenericInst *inst = type->data.generic_class->inst;
7030                 int i;
7031                 if (!inst->is_open)
7032                         break;
7033                 for (i = 0; i < inst->type_argc; ++i)
7034                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7035                                 return FALSE;
7036                 return TRUE;
7037         }
7038 #endif
7039         case MONO_TYPE_VAR:
7040         case MONO_TYPE_MVAR:
7041                 return TRUE;
7042         default:
7043                 return TRUE;
7044         }
7045 }
7046
7047 static MonoType*
7048 mono_type_normalize (MonoType *type)
7049 {
7050         int i;
7051         MonoGenericClass *gclass;
7052         MonoGenericInst *ginst;
7053         MonoClass *gtd;
7054         MonoGenericContainer *gcontainer;
7055         MonoType **argv = NULL;
7056         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7057
7058         if (type->type != MONO_TYPE_GENERICINST)
7059                 return type;
7060
7061         gclass = type->data.generic_class;
7062         ginst = gclass->context.class_inst;
7063         if (!ginst->is_open)
7064                 return type;
7065
7066         gtd = gclass->container_class;
7067         gcontainer = gtd->generic_container;
7068         argv = g_newa (MonoType*, ginst->type_argc);
7069
7070         for (i = 0; i < ginst->type_argc; ++i) {
7071                 MonoType *t = ginst->type_argv [i], *norm;
7072                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7073                         is_denorm_gtd = FALSE;
7074                 norm = mono_type_normalize (t);
7075                 argv [i] = norm;
7076                 if (norm != t)
7077                         requires_rebind = TRUE;
7078         }
7079
7080         if (is_denorm_gtd)
7081                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7082
7083         if (requires_rebind) {
7084                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7085                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7086         }
7087
7088         return type;
7089 }
7090 /*
7091  * mono_type_get_object:
7092  * @domain: an app domain
7093  * @type: a type
7094  *
7095  * Return an System.MonoType object representing the type @type.
7096  */
7097 MonoReflectionType*
7098 mono_type_get_object (MonoDomain *domain, MonoType *type)
7099 {
7100         MonoError error;
7101         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7102         mono_error_raise_exception (&error);
7103
7104         return ret;
7105 }
7106
7107 MonoReflectionType*
7108 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7109 {
7110         MonoType *norm_type;
7111         MonoReflectionType *res;
7112         MonoClass *klass;
7113
7114         mono_error_init (error);
7115
7116         klass = mono_class_from_mono_type (type);
7117
7118         /*we must avoid using @type as it might have come
7119          * from a mono_metadata_type_dup and the caller
7120          * expects that is can be freed.
7121          * Using the right type from 
7122          */
7123         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7124
7125         /* void is very common */
7126         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7127                 return (MonoReflectionType*)domain->typeof_void;
7128
7129         /*
7130          * If the vtable of the given class was already created, we can use
7131          * the MonoType from there and avoid all locking and hash table lookups.
7132          * 
7133          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7134          * that the resulting object is different.   
7135          */
7136         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7137                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7138                 if (vtable && vtable->type)
7139                         return (MonoReflectionType *)vtable->type;
7140         }
7141
7142         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7143         mono_domain_lock (domain);
7144         if (!domain->type_hash)
7145                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7146                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7147         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7148                 mono_domain_unlock (domain);
7149                 mono_loader_unlock ();
7150                 return res;
7151         }
7152
7153         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7154          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7155          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7156          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7157          * artifact of how generics are encoded and should be transparent to managed code so we
7158          * need to weed out this diference when retrieving managed System.Type objects.
7159          */
7160         norm_type = mono_type_normalize (type);
7161         if (norm_type != type) {
7162                 res = mono_type_get_object_checked (domain, norm_type, error);
7163                 if (!mono_error_ok (error))
7164                         return NULL;
7165                 mono_g_hash_table_insert (domain->type_hash, type, res);
7166                 mono_domain_unlock (domain);
7167                 mono_loader_unlock ();
7168                 return res;
7169         }
7170
7171         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7172         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7173                 g_assert (0);
7174
7175         if (!verify_safe_for_managed_space (type)) {
7176                 mono_domain_unlock (domain);
7177                 mono_loader_unlock ();
7178                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7179                 return NULL;
7180         }
7181
7182         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7183                 gboolean is_type_done = TRUE;
7184                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7185                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7186                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7187                 */
7188                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7189                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7190
7191                         if (gparam->owner && gparam->owner->is_method) {
7192                                 MonoMethod *method = gparam->owner->owner.method;
7193                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7194                                         is_type_done = FALSE;
7195                         } else if (gparam->owner && !gparam->owner->is_method) {
7196                                 MonoClass *klass = gparam->owner->owner.klass;
7197                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7198                                         is_type_done = FALSE;
7199                         }
7200                 } 
7201
7202                 /* g_assert_not_reached (); */
7203                 /* should this be considered an error condition? */
7204                 if (is_type_done && !type->byref) {
7205                         mono_domain_unlock (domain);
7206                         mono_loader_unlock ();
7207                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7208                 }
7209         }
7210         /* This is stored in vtables/JITted code so it has to be pinned */
7211         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7212         if (!mono_error_ok (error))
7213                 return NULL;
7214
7215         res->type = type;
7216         mono_g_hash_table_insert (domain->type_hash, type, res);
7217
7218         if (type->type == MONO_TYPE_VOID)
7219                 domain->typeof_void = (MonoObject*)res;
7220
7221         mono_domain_unlock (domain);
7222         mono_loader_unlock ();
7223         return res;
7224 }
7225
7226 /*
7227  * mono_method_get_object:
7228  * @domain: an app domain
7229  * @method: a method
7230  * @refclass: the reflected type (can be NULL)
7231  *
7232  * Return an System.Reflection.MonoMethod object representing the method @method.
7233  */
7234 MonoReflectionMethod*
7235 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7236 {
7237         MonoError error;
7238         MonoReflectionMethod *ret = NULL;
7239         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7240         mono_error_raise_exception (&error);
7241         return ret;
7242 }
7243
7244 /*
7245  * mono_method_get_object_checked:
7246  * @domain: an app domain
7247  * @method: a method
7248  * @refclass: the reflected type (can be NULL)
7249  * @error: set on error.
7250  *
7251  * Return an System.Reflection.MonoMethod object representing the method @method.
7252  * Returns NULL and sets @error on error.
7253  */
7254 MonoReflectionMethod*
7255 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7256 {
7257         /*
7258          * We use the same C representation for methods and constructors, but the type 
7259          * name in C# is different.
7260          */
7261         MonoReflectionType *rt;
7262         MonoClass *klass;
7263         MonoReflectionMethod *ret;
7264
7265         mono_error_init (error);
7266
7267         if (method->is_inflated) {
7268                 MonoReflectionGenericMethod *gret;
7269
7270                 if (!refclass)
7271                         refclass = method->klass;
7272                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7273                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7274                         klass = mono_class_get_mono_generic_cmethod_class ();
7275                 } else {
7276                         klass = mono_class_get_mono_generic_method_class ();
7277                 }
7278                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7279                 if (!mono_error_ok (error))
7280                         goto leave;
7281                 gret->method.method = method;
7282
7283                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7284
7285                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7286                 if (!mono_error_ok (error))
7287                     goto leave;
7288
7289                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7290
7291                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7292         }
7293
7294         if (!refclass)
7295                 refclass = method->klass;
7296
7297         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7298         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7299                 klass = mono_class_get_mono_cmethod_class ();
7300         }
7301         else {
7302                 klass = mono_class_get_mono_method_class ();
7303         }
7304         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7305         if (!mono_error_ok (error))
7306                 goto leave;
7307         ret->method = method;
7308
7309         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7310         if (!mono_error_ok (error))
7311                 goto leave;
7312
7313         MONO_OBJECT_SETREF (ret, reftype, rt);
7314
7315         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7316
7317 leave:
7318         g_assert (!mono_error_ok (error));
7319         return NULL;
7320 }
7321
7322 /*
7323  * mono_method_clear_object:
7324  *
7325  *   Clear the cached reflection objects for the dynamic method METHOD.
7326  */
7327 void
7328 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7329 {
7330         MonoClass *klass;
7331         g_assert (method_is_dynamic (method));
7332
7333         klass = method->klass;
7334         while (klass) {
7335                 clear_cached_object (domain, method, klass);
7336                 klass = klass->parent;
7337         }
7338         /* Added by mono_param_get_objects () */
7339         clear_cached_object (domain, &(method->signature), NULL);
7340         klass = method->klass;
7341         while (klass) {
7342                 clear_cached_object (domain, &(method->signature), klass);
7343                 klass = klass->parent;
7344         }
7345 }
7346
7347 /*
7348  * mono_field_get_object:
7349  * @domain: an app domain
7350  * @klass: a type
7351  * @field: a field
7352  *
7353  * Return an System.Reflection.MonoField object representing the field @field
7354  * in class @klass.
7355  */
7356 MonoReflectionField*
7357 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7358 {
7359         MonoError error;
7360         MonoReflectionField *result;
7361         result = mono_field_get_object_checked (domain, klass, field, &error);
7362         mono_error_raise_exception (&error);
7363         return result;
7364 }
7365
7366 /*
7367  * mono_field_get_object_checked:
7368  * @domain: an app domain
7369  * @klass: a type
7370  * @field: a field
7371  * @error: set on error
7372  *
7373  * Return an System.Reflection.MonoField object representing the field @field
7374  * in class @klass. On error, returns NULL and sets @error.
7375  */
7376 MonoReflectionField*
7377 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7378 {
7379         MonoReflectionType *rt;
7380         MonoReflectionField *res;
7381
7382         mono_error_init (error);
7383
7384         CHECK_OBJECT (MonoReflectionField *, field, klass);
7385         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7386         if (!res)
7387                 return NULL;
7388         res->klass = klass;
7389         res->field = field;
7390         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7391
7392         if (is_field_on_inst (field)) {
7393                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7394
7395                 rt = mono_type_get_object_checked (domain, field->type, error);
7396                 if (!mono_error_ok (error))
7397                         return NULL;
7398
7399                 MONO_OBJECT_SETREF (res, type, rt);
7400         } else {
7401                 if (field->type) {
7402                         rt = mono_type_get_object_checked (domain, field->type, error);
7403                         if (!mono_error_ok (error))
7404                                 return NULL;
7405
7406                         MONO_OBJECT_SETREF (res, type, rt);
7407                 }
7408                 res->attrs = mono_field_get_flags (field);
7409         }
7410         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7411 }
7412
7413 /*
7414  * mono_property_get_object:
7415  * @domain: an app domain
7416  * @klass: a type
7417  * @property: a property
7418  *
7419  * Return an System.Reflection.MonoProperty object representing the property @property
7420  * in class @klass.
7421  */
7422 MonoReflectionProperty*
7423 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7424 {
7425         MonoError error;
7426         MonoReflectionProperty *result;
7427         result = mono_property_get_object_checked (domain, klass, property, &error);
7428         mono_error_raise_exception (&error);
7429         return result;
7430 }
7431
7432 /**
7433  * mono_property_get_object:
7434  * @domain: an app domain
7435  * @klass: a type
7436  * @property: a property
7437  * @error: set on error
7438  *
7439  * Return an System.Reflection.MonoProperty object representing the property @property
7440  * in class @klass.  On error returns NULL and sets @error.
7441  */
7442 MonoReflectionProperty*
7443 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7444 {
7445         MonoReflectionProperty *res;
7446
7447         mono_error_init (error);
7448
7449         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7450         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7451         if (!res)
7452                 return NULL;
7453         res->klass = klass;
7454         res->property = property;
7455         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7456 }
7457
7458 /*
7459  * mono_event_get_object:
7460  * @domain: an app domain
7461  * @klass: a type
7462  * @event: a event
7463  *
7464  * Return an System.Reflection.MonoEvent object representing the event @event
7465  * in class @klass.
7466  */
7467 MonoReflectionEvent*
7468 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7469 {
7470         MonoError error;
7471         MonoReflectionEvent *result;
7472         result = mono_event_get_object_checked (domain, klass, event, &error);
7473         mono_error_raise_exception (&error);
7474         return result;
7475 }
7476
7477 /**
7478  * mono_event_get_object_checked:
7479  * @domain: an app domain
7480  * @klass: a type
7481  * @event: a event
7482  * @error: set on error
7483  *
7484  * Return an System.Reflection.MonoEvent object representing the event @event
7485  * in class @klass. On failure sets @error and returns NULL
7486  */
7487 MonoReflectionEvent*
7488 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7489 {
7490         MonoReflectionEvent *res;
7491         MonoReflectionMonoEvent *mono_event;
7492
7493         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7494         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7495         if (!mono_event)
7496                 return NULL;
7497         mono_event->klass = klass;
7498         mono_event->event = event;
7499         res = (MonoReflectionEvent*)mono_event;
7500         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7501 }
7502
7503 /**
7504  * mono_get_reflection_missing_object:
7505  * @domain: Domain where the object lives
7506  *
7507  * Returns the System.Reflection.Missing.Value singleton object
7508  * (of type System.Reflection.Missing).
7509  *
7510  * Used as the value for ParameterInfo.DefaultValue when Optional
7511  * is present
7512  */
7513 static MonoObject *
7514 mono_get_reflection_missing_object (MonoDomain *domain)
7515 {
7516         MonoObject *obj;
7517         static MonoClassField *missing_value_field = NULL;
7518         
7519         if (!missing_value_field) {
7520                 MonoClass *missing_klass;
7521                 missing_klass = mono_class_get_missing_class ();
7522                 mono_class_init (missing_klass);
7523                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7524                 g_assert (missing_value_field);
7525         }
7526         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7527         g_assert (obj);
7528         return obj;
7529 }
7530
7531 static MonoObject*
7532 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7533 {
7534         if (!*dbnull)
7535                 *dbnull = mono_get_dbnull_object (domain);
7536         return *dbnull;
7537 }
7538
7539 static MonoObject*
7540 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7541 {
7542         if (!*reflection_missing)
7543                 *reflection_missing = mono_get_reflection_missing_object (domain);
7544         return *reflection_missing;
7545 }
7546
7547 /*
7548  * mono_param_get_objects:
7549  * @domain: an app domain
7550  * @method: a method
7551  *
7552  * Return an System.Reflection.ParameterInfo array object representing the parameters
7553  * in the method @method.
7554  */
7555 MonoArray*
7556 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7557 {
7558         static MonoClass *System_Reflection_ParameterInfo;
7559         static MonoClass *System_Reflection_ParameterInfo_array;
7560         MonoError error;
7561         MonoArray *res = NULL;
7562         MonoReflectionMethod *member = NULL;
7563         MonoReflectionParameter *param = NULL;
7564         char **names = NULL, **blobs = NULL;
7565         guint32 *types = NULL;
7566         MonoType *type = NULL;
7567         MonoObject *dbnull = NULL;
7568         MonoObject *missing = NULL;
7569         MonoMarshalSpec **mspecs = NULL;
7570         MonoMethodSignature *sig = NULL;
7571         MonoVTable *pinfo_vtable;
7572         MonoReflectionType *rt;
7573         int i;
7574
7575         mono_error_init (&error);
7576         
7577         if (!System_Reflection_ParameterInfo_array) {
7578                 MonoClass *klass;
7579
7580                 klass = mono_class_get_mono_parameter_info_class ();
7581
7582                 mono_memory_barrier ();
7583                 System_Reflection_ParameterInfo = klass; 
7584
7585         
7586                 klass = mono_array_class_get (klass, 1);
7587                 mono_memory_barrier ();
7588                 System_Reflection_ParameterInfo_array = klass;
7589         }
7590
7591         sig = mono_method_signature_checked (method, &error);
7592         if (!mono_error_ok (&error))
7593                 goto leave;
7594
7595         if (!sig->param_count) {
7596                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7597                 if (!res)
7598                         goto leave;
7599
7600                 return res;
7601         }
7602
7603         /* Note: the cache is based on the address of the signature into the method
7604          * since we already cache MethodInfos with the method as keys.
7605          */
7606         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7607
7608         member = mono_method_get_object_checked (domain, method, refclass, &error);
7609         if (!member)
7610                 goto leave;
7611         names = g_new (char *, sig->param_count);
7612         mono_method_get_param_names (method, (const char **) names);
7613
7614         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7615         mono_method_get_marshal_info (method, mspecs);
7616
7617         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7618         if (!res)
7619                 goto leave;
7620
7621         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7622         for (i = 0; i < sig->param_count; ++i) {
7623                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7624                 if (!param)
7625                         goto leave;
7626
7627                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7628                 if (!rt)
7629                         goto leave;
7630
7631                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7632
7633                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7634
7635                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7636
7637                 param->PositionImpl = i;
7638                 param->AttrsImpl = sig->params [i]->attrs;
7639
7640                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7641                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7642                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7643                         else
7644                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7645                 } else {
7646
7647                         if (!blobs) {
7648                                 blobs = g_new0 (char *, sig->param_count);
7649                                 types = g_new0 (guint32, sig->param_count);
7650                                 get_default_param_value_blobs (method, blobs, types); 
7651                         }
7652
7653                         /* Build MonoType for the type from the Constant Table */
7654                         if (!type)
7655                                 type = g_new0 (MonoType, 1);
7656                         type->type = (MonoTypeEnum)types [i];
7657                         type->data.klass = NULL;
7658                         if (types [i] == MONO_TYPE_CLASS)
7659                                 type->data.klass = mono_defaults.object_class;
7660                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7661                                 /* For enums, types [i] contains the base type */
7662
7663                                         type->type = MONO_TYPE_VALUETYPE;
7664                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7665                         } else
7666                                 type->data.klass = mono_class_from_mono_type (type);
7667
7668                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7669
7670                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7671                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7672                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7673                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7674                                 else
7675                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7676                         }
7677                         
7678                 }
7679
7680                 if (mspecs [i + 1]) {
7681                         MonoReflectionMarshalAsAttribute* mobj;
7682                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7683                         if (!mobj)
7684                                 goto leave;
7685                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7686                 }
7687                 
7688                 mono_array_setref (res, i, param);
7689         }
7690
7691 leave:
7692         g_free (names);
7693         g_free (blobs);
7694         g_free (types);
7695         g_free (type);
7696
7697         if (sig) {
7698                 for (i = sig->param_count; i >= 0; i--) {
7699                         if (mspecs [i])
7700                                 mono_metadata_free_marshal_spec (mspecs [i]);
7701                 }
7702         }
7703         g_free (mspecs);
7704
7705         mono_error_raise_exception (&error); /* FIXME don't raise here */
7706         
7707         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7708 }
7709
7710 MonoArray*
7711 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7712 {
7713         return mono_param_get_objects_internal (domain, method, NULL);
7714 }
7715
7716 /*
7717  * mono_method_body_get_object:
7718  * @domain: an app domain
7719  * @method: a method
7720  *
7721  * Return an System.Reflection.MethodBody object representing the method @method.
7722  */
7723 MonoReflectionMethodBody*
7724 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7725 {
7726         MonoError error;
7727         MonoReflectionMethodBody *ret;
7728         MonoMethodHeader *header;
7729         MonoImage *image;
7730         MonoReflectionType *rt;
7731         guint32 method_rva, local_var_sig_token;
7732     char *ptr;
7733         unsigned char format, flags;
7734         int i;
7735
7736         /* for compatibility with .net */
7737     if (method_is_dynamic (method))
7738         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7739
7740         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7741
7742         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7743                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7744             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7745                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7746             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7747                 return NULL;
7748
7749         image = method->klass->image;
7750         header = mono_method_get_header_checked (method, &error);
7751         mono_error_raise_exception (&error); /* FIXME don't raise here */
7752
7753         if (!image_is_dynamic (image)) {
7754                 /* Obtain local vars signature token */
7755                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7756                 ptr = mono_image_rva_map (image, method_rva);
7757                 flags = *(const unsigned char *) ptr;
7758                 format = flags & METHOD_HEADER_FORMAT_MASK;
7759                 switch (format){
7760                 case METHOD_HEADER_TINY_FORMAT:
7761                         local_var_sig_token = 0;
7762                         break;
7763                 case METHOD_HEADER_FAT_FORMAT:
7764                         ptr += 2;
7765                         ptr += 2;
7766                         ptr += 4;
7767                         local_var_sig_token = read32 (ptr);
7768                         break;
7769                 default:
7770                         g_assert_not_reached ();
7771                 }
7772         } else
7773                 local_var_sig_token = 0; //FIXME
7774
7775         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7776         mono_error_raise_exception (&error); /* FIXME don't raise here */
7777
7778         ret->init_locals = header->init_locals;
7779         ret->max_stack = header->max_stack;
7780         ret->local_var_sig_token = local_var_sig_token;
7781         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7782         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7783
7784         /* Locals */
7785         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7786         for (i = 0; i < header->num_locals; ++i) {
7787                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7788                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7789
7790                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7791                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7792
7793                 MONO_OBJECT_SETREF (info, local_type, rt);
7794
7795                 info->is_pinned = header->locals [i]->pinned;
7796                 info->local_index = i;
7797                 mono_array_setref (ret->locals, i, info);
7798         }
7799
7800         /* Exceptions */
7801         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7802         for (i = 0; i < header->num_clauses; ++i) {
7803                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7804                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7805                 MonoExceptionClause *clause = &header->clauses [i];
7806
7807                 info->flags = clause->flags;
7808                 info->try_offset = clause->try_offset;
7809                 info->try_length = clause->try_len;
7810                 info->handler_offset = clause->handler_offset;
7811                 info->handler_length = clause->handler_len;
7812                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7813                         info->filter_offset = clause->data.filter_offset;
7814                 else if (clause->data.catch_class) {
7815                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7816                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7817
7818                         MONO_OBJECT_SETREF (info, catch_type, rt);
7819                 }
7820
7821                 mono_array_setref (ret->clauses, i, info);
7822         }
7823
7824         mono_metadata_free_mh (header);
7825         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7826         return ret;
7827 }
7828
7829 /**
7830  * mono_get_dbnull_object:
7831  * @domain: Domain where the object lives
7832  *
7833  * Returns the System.DBNull.Value singleton object
7834  *
7835  * Used as the value for ParameterInfo.DefaultValue 
7836  */
7837 MonoObject *
7838 mono_get_dbnull_object (MonoDomain *domain)
7839 {
7840         MonoObject *obj;
7841         static MonoClassField *dbnull_value_field = NULL;
7842         
7843         if (!dbnull_value_field) {
7844                 MonoClass *dbnull_klass;
7845                 dbnull_klass = mono_class_get_dbnull_class ();
7846                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7847                 g_assert (dbnull_value_field);
7848         }
7849         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7850         g_assert (obj);
7851         return obj;
7852 }
7853
7854 static void
7855 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7856 {
7857         guint32 param_index, i, lastp, crow = 0;
7858         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7859         gint32 idx;
7860
7861         MonoClass *klass = method->klass;
7862         MonoImage *image = klass->image;
7863         MonoMethodSignature *methodsig = mono_method_signature (method);
7864
7865         MonoTableInfo *constt;
7866         MonoTableInfo *methodt;
7867         MonoTableInfo *paramt;
7868
7869         if (!methodsig->param_count)
7870                 return;
7871
7872         mono_class_init (klass);
7873
7874         if (image_is_dynamic (klass->image)) {
7875                 MonoReflectionMethodAux *aux;
7876                 if (method->is_inflated)
7877                         method = ((MonoMethodInflated*)method)->declaring;
7878                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7879                 if (aux && aux->param_defaults) {
7880                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7881                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7882                 }
7883                 return;
7884         }
7885
7886         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7887         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7888         constt = &image->tables [MONO_TABLE_CONSTANT];
7889
7890         idx = mono_method_get_index (method) - 1;
7891         g_assert (idx != -1);
7892
7893         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7894         if (idx + 1 < methodt->rows)
7895                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7896         else
7897                 lastp = paramt->rows + 1;
7898
7899         for (i = param_index; i < lastp; ++i) {
7900                 guint32 paramseq;
7901
7902                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7903                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7904
7905                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7906                         continue;
7907
7908                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7909                 if (!crow) {
7910                         continue;
7911                 }
7912         
7913                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7914                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7915                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7916         }
7917
7918         return;
7919 }
7920
7921 MonoObject *
7922 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7923 {
7924         MonoError error;
7925         void *retval;
7926         MonoClass *klass;
7927         MonoObject *object;
7928         MonoType *basetype = type;
7929
7930         if (!blob)
7931                 return NULL;
7932         
7933         klass = mono_class_from_mono_type (type);
7934         if (klass->valuetype) {
7935                 object = mono_object_new_checked (domain, klass, &error);
7936                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7937                 retval = ((gchar *) object + sizeof (MonoObject));
7938                 if (klass->enumtype)
7939                         basetype = mono_class_enum_basetype (klass);
7940         } else {
7941                 retval = &object;
7942         }
7943                         
7944         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7945                 return object;
7946         else
7947                 return NULL;
7948 }
7949
7950 static int
7951 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7952         int found_sep;
7953         char *s;
7954         gboolean quoted = FALSE;
7955
7956         memset (assembly, 0, sizeof (MonoAssemblyName));
7957         assembly->culture = "";
7958         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7959
7960         if (*p == '"') {
7961                 quoted = TRUE;
7962                 p++;
7963         }
7964         assembly->name = p;
7965         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7966                 p++;
7967         if (quoted) {
7968                 if (*p != '"')
7969                         return 1;
7970                 *p = 0;
7971                 p++;
7972         }
7973         if (*p != ',')
7974                 return 1;
7975         *p = 0;
7976         /* Remove trailing whitespace */
7977         s = p - 1;
7978         while (*s && g_ascii_isspace (*s))
7979                 *s-- = 0;
7980         p ++;
7981         while (g_ascii_isspace (*p))
7982                 p++;
7983         while (*p) {
7984                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7985                         p += 8;
7986                         assembly->major = strtoul (p, &s, 10);
7987                         if (s == p || *s != '.')
7988                                 return 1;
7989                         p = ++s;
7990                         assembly->minor = strtoul (p, &s, 10);
7991                         if (s == p || *s != '.')
7992                                 return 1;
7993                         p = ++s;
7994                         assembly->build = strtoul (p, &s, 10);
7995                         if (s == p || *s != '.')
7996                                 return 1;
7997                         p = ++s;
7998                         assembly->revision = strtoul (p, &s, 10);
7999                         if (s == p)
8000                                 return 1;
8001                         p = s;
8002                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8003                         p += 8;
8004                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8005                                 assembly->culture = "";
8006                                 p += 7;
8007                         } else {
8008                                 assembly->culture = p;
8009                                 while (*p && *p != ',') {
8010                                         p++;
8011                                 }
8012                         }
8013                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8014                         p += 15;
8015                         if (strncmp (p, "null", 4) == 0) {
8016                                 p += 4;
8017                         } else {
8018                                 int len;
8019                                 gchar *start = p;
8020                                 while (*p && *p != ',') {
8021                                         p++;
8022                                 }
8023                                 len = (p - start + 1);
8024                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8025                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8026                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8027                         }
8028                 } else {
8029                         while (*p && *p != ',')
8030                                 p++;
8031                 }
8032                 found_sep = 0;
8033                 while (g_ascii_isspace (*p) || *p == ',') {
8034                         *p++ = 0;
8035                         found_sep = 1;
8036                         continue;
8037                 }
8038                 /* failed */
8039                 if (!found_sep)
8040                         return 1;
8041         }
8042
8043         return 0;
8044 }
8045
8046 /*
8047  * mono_reflection_parse_type:
8048  * @name: type name
8049  *
8050  * Parse a type name as accepted by the GetType () method and output the info
8051  * extracted in the info structure.
8052  * the name param will be mangled, so, make a copy before passing it to this function.
8053  * The fields in info will be valid until the memory pointed to by name is valid.
8054  *
8055  * See also mono_type_get_name () below.
8056  *
8057  * Returns: 0 on parse error.
8058  */
8059 static int
8060 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8061                              MonoTypeNameParse *info)
8062 {
8063         char *start, *p, *w, *last_point, *startn;
8064         int in_modifiers = 0;
8065         int isbyref = 0, rank = 0, isptr = 0;
8066
8067         start = p = w = name;
8068
8069         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8070         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8071         info->name = info->name_space = NULL;
8072         info->nested = NULL;
8073         info->modifiers = NULL;
8074         info->type_arguments = NULL;
8075
8076         /* last_point separates the namespace from the name */
8077         last_point = NULL;
8078         /* Skips spaces */
8079         while (*p == ' ') p++, start++, w++, name++;
8080
8081         while (*p) {
8082                 switch (*p) {
8083                 case '+':
8084                         *p = 0; /* NULL terminate the name */
8085                         startn = p + 1;
8086                         info->nested = g_list_append (info->nested, startn);
8087                         /* we have parsed the nesting namespace + name */
8088                         if (info->name)
8089                                 break;
8090                         if (last_point) {
8091                                 info->name_space = start;
8092                                 *last_point = 0;
8093                                 info->name = last_point + 1;
8094                         } else {
8095                                 info->name_space = (char *)"";
8096                                 info->name = start;
8097                         }
8098                         break;
8099                 case '.':
8100                         last_point = p;
8101                         break;
8102                 case '\\':
8103                         ++p;
8104                         break;
8105                 case '&':
8106                 case '*':
8107                 case '[':
8108                 case ',':
8109                 case ']':
8110                         in_modifiers = 1;
8111                         break;
8112                 default:
8113                         break;
8114                 }
8115                 if (in_modifiers)
8116                         break;
8117                 // *w++ = *p++;
8118                 p++;
8119         }
8120         
8121         if (!info->name) {
8122                 if (last_point) {
8123                         info->name_space = start;
8124                         *last_point = 0;
8125                         info->name = last_point + 1;
8126                 } else {
8127                         info->name_space = (char *)"";
8128                         info->name = start;
8129                 }
8130         }
8131         while (*p) {
8132                 switch (*p) {
8133                 case '&':
8134                         if (isbyref) /* only one level allowed by the spec */
8135                                 return 0;
8136                         isbyref = 1;
8137                         isptr = 0;
8138                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8139                         *p++ = 0;
8140                         break;
8141                 case '*':
8142                         if (isbyref) /* pointer to ref not okay */
8143                                 return 0;
8144                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8145                         isptr = 1;
8146                         *p++ = 0;
8147                         break;
8148                 case '[':
8149                         if (isbyref) /* array of ref and generic ref are not okay */
8150                                 return 0;
8151                         //Decide if it's an array of a generic argument list
8152                         *p++ = 0;
8153
8154                         if (!*p) //XXX test
8155                                 return 0;
8156                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8157                                 isptr = 0;
8158                                 rank = 1;
8159                                 while (*p) {
8160                                         if (*p == ']')
8161                                                 break;
8162                                         if (*p == ',')
8163                                                 rank++;
8164                                         else if (*p == '*') /* '*' means unknown lower bound */
8165                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8166                                         else
8167                                                 return 0;
8168                                         ++p;
8169                                 }
8170                                 if (*p++ != ']')
8171                                         return 0;
8172                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8173                         } else {
8174                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8175                                         return 0;
8176                                 isptr = 0;
8177                                 info->type_arguments = g_ptr_array_new ();
8178                                 while (*p) {
8179                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8180                                         gboolean fqname = FALSE;
8181
8182                                         g_ptr_array_add (info->type_arguments, subinfo);
8183
8184                                         while (*p == ' ') p++;
8185                                         if (*p == '[') {
8186                                                 p++;
8187                                                 fqname = TRUE;
8188                                         }
8189
8190                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8191                                                 return 0;
8192
8193                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8194                                         if (fqname && (*p != ']')) {
8195                                                 char *aname;
8196
8197                                                 if (*p != ',')
8198                                                         return 0;
8199                                                 *p++ = 0;
8200
8201                                                 aname = p;
8202                                                 while (*p && (*p != ']'))
8203                                                         p++;
8204
8205                                                 if (*p != ']')
8206                                                         return 0;
8207
8208                                                 *p++ = 0;
8209                                                 while (*aname) {
8210                                                         if (g_ascii_isspace (*aname)) {
8211                                                                 ++aname;
8212                                                                 continue;
8213                                                         }
8214                                                         break;
8215                                                 }
8216                                                 if (!*aname ||
8217                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8218                                                         return 0;
8219                                         } else if (fqname && (*p == ']')) {
8220                                                 *p++ = 0;
8221                                         }
8222                                         if (*p == ']') {
8223                                                 *p++ = 0;
8224                                                 break;
8225                                         } else if (!*p) {
8226                                                 return 0;
8227                                         }
8228                                         *p++ = 0;
8229                                 }
8230                         }
8231                         break;
8232                 case ']':
8233                         if (is_recursed)
8234                                 goto end;
8235                         return 0;
8236                 case ',':
8237                         if (is_recursed)
8238                                 goto end;
8239                         *p++ = 0;
8240                         while (*p) {
8241                                 if (g_ascii_isspace (*p)) {
8242                                         ++p;
8243                                         continue;
8244                                 }
8245                                 break;
8246                         }
8247                         if (!*p)
8248                                 return 0; /* missing assembly name */
8249                         if (!assembly_name_to_aname (&info->assembly, p))
8250                                 return 0;
8251                         break;
8252                 default:
8253                         return 0;
8254                 }
8255                 if (info->assembly.name)
8256                         break;
8257         }
8258         // *w = 0; /* terminate class name */
8259  end:
8260         if (!info->name || !*info->name)
8261                 return 0;
8262         if (endptr)
8263                 *endptr = p;
8264         /* add other consistency checks */
8265         return 1;
8266 }
8267
8268
8269 /**
8270  * mono_identifier_unescape_type_name_chars:
8271  * @identifier: the display name of a mono type
8272  *
8273  * Returns:
8274  *  The name in internal form, that is without escaping backslashes.
8275  *
8276  *  The string is modified in place!
8277  */
8278 char*
8279 mono_identifier_unescape_type_name_chars(char* identifier)
8280 {
8281         char *w, *r;
8282         if (!identifier)
8283                 return NULL;
8284         for (w = r = identifier; *r != 0; r++)
8285         {
8286                 char c = *r;
8287                 if (c == '\\') {
8288                         r++;
8289                         if (*r == 0)
8290                                 break;
8291                         c = *r;
8292                 }
8293                 *w = c;
8294                 w++;
8295         }
8296         if (w != r)
8297                 *w = 0;
8298         return identifier;
8299 }
8300
8301 void
8302 mono_identifier_unescape_info (MonoTypeNameParse* info);
8303
8304 static void
8305 unescape_each_type_argument(void* data, void* user_data)
8306 {
8307         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8308         mono_identifier_unescape_info (info);
8309 }
8310
8311 static void
8312 unescape_each_nested_name (void* data, void* user_data)
8313 {
8314         char* nested_name = (char*) data;
8315         mono_identifier_unescape_type_name_chars(nested_name);
8316 }
8317
8318 /**
8319  * mono_identifier_unescape_info:
8320  *
8321  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8322  *
8323  * Returns: nothing.
8324  *
8325  * Destructively updates the info by unescaping the identifiers that
8326  * comprise the type namespace, name, nested types (if any) and
8327  * generic type arguments (if any).
8328  *
8329  * The resulting info has the names in internal form.
8330  *
8331  */
8332 void
8333 mono_identifier_unescape_info (MonoTypeNameParse *info)
8334 {
8335         if (!info)
8336                 return;
8337         mono_identifier_unescape_type_name_chars(info->name_space);
8338         mono_identifier_unescape_type_name_chars(info->name);
8339         // but don't escape info->assembly
8340         if (info->type_arguments)
8341                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8342         if (info->nested)
8343                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8344 }
8345
8346 int
8347 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8348 {
8349         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8350         if (ok) {
8351                 mono_identifier_unescape_info (info);
8352         }
8353         return ok;
8354 }
8355
8356 static MonoType*
8357 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8358 {
8359         gboolean type_resolve = FALSE;
8360         MonoType *type;
8361         MonoImage *rootimage = image;
8362
8363         if (info->assembly.name) {
8364                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8365                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8366                         /* 
8367                          * This could happen in the AOT compiler case when the search hook is not
8368                          * installed.
8369                          */
8370                         assembly = image->assembly;
8371                 if (!assembly) {
8372                         /* then we must load the assembly ourselve - see #60439 */
8373                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8374                         if (!assembly)
8375                                 return NULL;
8376                 }
8377                 image = assembly->image;
8378         } else if (!image) {
8379                 image = mono_defaults.corlib;
8380         }
8381
8382         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8383         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8384                 image = mono_defaults.corlib;
8385                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8386         }
8387
8388         return type;
8389 }
8390
8391 /**
8392  * mono_reflection_get_type_internal:
8393  *
8394  * Returns: may return NULL on success, sets error on failure.
8395  */
8396 static MonoType*
8397 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8398 {
8399         MonoClass *klass;
8400         GList *mod;
8401         int modval;
8402         gboolean bounded = FALSE;
8403         
8404         mono_error_init (error);
8405         if (!image)
8406                 image = mono_defaults.corlib;
8407
8408         if (!rootimage)
8409                 rootimage = mono_defaults.corlib;
8410
8411         if (ignorecase)
8412                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8413         else
8414                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8415
8416         if (!klass)
8417                 return NULL;
8418
8419         for (mod = info->nested; mod; mod = mod->next) {
8420                 gpointer iter = NULL;
8421                 MonoClass *parent;
8422
8423                 parent = klass;
8424                 mono_class_init (parent);
8425
8426                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8427                         char *lastp;
8428                         char *nested_name, *nested_nspace;
8429                         gboolean match = TRUE;
8430
8431                         lastp = strrchr ((const char *)mod->data, '.');
8432                         if (lastp) {
8433                                 /* Nested classes can have namespaces */
8434                                 int nspace_len;
8435
8436                                 nested_name = g_strdup (lastp + 1);
8437                                 nspace_len = lastp - (char*)mod->data;
8438                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8439                                 memcpy (nested_nspace, mod->data, nspace_len);
8440                                 nested_nspace [nspace_len] = '\0';
8441
8442                         } else {
8443                                 nested_name = (char *)mod->data;
8444                                 nested_nspace = NULL;
8445                         }
8446
8447                         if (nested_nspace) {
8448                                 if (ignorecase) {
8449                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8450                                                 match = FALSE;
8451                                 } else {
8452                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8453                                                 match = FALSE;
8454                                 }
8455                         }
8456                         if (match) {
8457                                 if (ignorecase) {
8458                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8459                                                 match = FALSE;
8460                                 } else {
8461                                         if (strcmp (klass->name, nested_name) != 0)
8462                                                 match = FALSE;
8463                                 }
8464                         }
8465                         if (lastp) {
8466                                 g_free (nested_name);
8467                                 g_free (nested_nspace);
8468                         }
8469                         if (match)
8470                                 break;
8471                 }
8472
8473                 if (!klass)
8474                         break;
8475         }
8476         if (!klass)
8477                 return NULL;
8478
8479         if (info->type_arguments) {
8480                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8481                 MonoReflectionType *the_type;
8482                 MonoType *instance;
8483                 int i;
8484
8485                 for (i = 0; i < info->type_arguments->len; i++) {
8486                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8487
8488                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8489                         if (!type_args [i]) {
8490                                 g_free (type_args);
8491                                 return NULL;
8492                         }
8493                 }
8494
8495                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8496                 if (!the_type)
8497                         return NULL;
8498
8499                 instance = mono_reflection_bind_generic_parameters (
8500                         the_type, info->type_arguments->len, type_args);
8501
8502                 g_free (type_args);
8503                 if (!instance)
8504                         return NULL;
8505
8506                 klass = mono_class_from_mono_type (instance);
8507         }
8508
8509         for (mod = info->modifiers; mod; mod = mod->next) {
8510                 modval = GPOINTER_TO_UINT (mod->data);
8511                 if (!modval) { /* byref: must be last modifier */
8512                         return &klass->this_arg;
8513                 } else if (modval == -1) {
8514                         klass = mono_ptr_class_get (&klass->byval_arg);
8515                 } else if (modval == -2) {
8516                         bounded = TRUE;
8517                 } else { /* array rank */
8518                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8519                 }
8520         }
8521
8522         return &klass->byval_arg;
8523 }
8524
8525 /*
8526  * mono_reflection_get_type:
8527  * @image: a metadata context
8528  * @info: type description structure
8529  * @ignorecase: flag for case-insensitive string compares
8530  * @type_resolve: whenever type resolve was already tried
8531  *
8532  * Build a MonoType from the type description in @info.
8533  * 
8534  */
8535
8536 MonoType*
8537 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8538         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8539 }
8540
8541 static MonoType*
8542 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8543 {
8544         MonoReflectionAssemblyBuilder *abuilder;
8545         MonoType *type;
8546         int i;
8547
8548         mono_error_init (error);
8549         g_assert (assembly_is_dynamic (assembly));
8550         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8551         if (!abuilder)
8552                 return NULL;
8553
8554         /* Enumerate all modules */
8555
8556         type = NULL;
8557         if (abuilder->modules) {
8558                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8559                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8560                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8561                         if (type)
8562                                 break;
8563                         if (!mono_error_ok (error))
8564                                 return NULL;
8565                 }
8566         }
8567
8568         if (!type && abuilder->loaded_modules) {
8569                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8570                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8571                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8572                         if (type)
8573                                 break;
8574                         if (!mono_error_ok (error))
8575                                 return NULL;
8576                 }
8577         }
8578
8579         return type;
8580 }
8581         
8582 MonoType*
8583 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8584 {
8585         MonoError error;
8586         MonoType *type;
8587         MonoReflectionAssembly *assembly;
8588         GString *fullName;
8589         GList *mod;
8590
8591         if (image && image_is_dynamic (image))
8592                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8593         else {
8594                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8595         }
8596         if (!mono_error_ok (&error))
8597                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8598
8599         if (type)
8600                 return type;
8601         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8602                 return NULL;
8603
8604         if (type_resolve) {
8605                 if (*type_resolve) 
8606                         return NULL;
8607                 else
8608                         *type_resolve = TRUE;
8609         }
8610         
8611         /* Reconstruct the type name */
8612         fullName = g_string_new ("");
8613         if (info->name_space && (info->name_space [0] != '\0'))
8614                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8615         else
8616                 g_string_printf (fullName, "%s", info->name);
8617         for (mod = info->nested; mod; mod = mod->next)
8618                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8619
8620         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8621         mono_error_raise_exception (&error); /* FIXME don't raise here */
8622
8623         if (assembly) {
8624                 if (assembly_is_dynamic (assembly->assembly))
8625                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8626                                                                           info, ignorecase, &error);
8627                 else
8628                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8629                                                                   info, ignorecase, &error);
8630         }
8631         g_string_free (fullName, TRUE);
8632         if (!mono_error_ok (&error))
8633                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8634         return type;
8635 }
8636
8637 void
8638 mono_reflection_free_type_info (MonoTypeNameParse *info)
8639 {
8640         g_list_free (info->modifiers);
8641         g_list_free (info->nested);
8642
8643         if (info->type_arguments) {
8644                 int i;
8645
8646                 for (i = 0; i < info->type_arguments->len; i++) {
8647                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8648
8649                         mono_reflection_free_type_info (subinfo);
8650                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8651                         g_free (subinfo);
8652                 }
8653
8654                 g_ptr_array_free (info->type_arguments, TRUE);
8655         }
8656 }
8657
8658 /*
8659  * mono_reflection_type_from_name:
8660  * @name: type name.
8661  * @image: a metadata context (can be NULL).
8662  *
8663  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8664  * it defaults to get the type from @image or, if @image is NULL or loading
8665  * from it fails, uses corlib.
8666  * 
8667  */
8668 MonoType*
8669 mono_reflection_type_from_name (char *name, MonoImage *image)
8670 {
8671         MonoType *type = NULL;
8672         MonoTypeNameParse info;
8673         char *tmp;
8674
8675         /* Make a copy since parse_type modifies its argument */
8676         tmp = g_strdup (name);
8677         
8678         /*g_print ("requested type %s\n", str);*/
8679         if (mono_reflection_parse_type (tmp, &info)) {
8680                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8681         }
8682
8683         g_free (tmp);
8684         mono_reflection_free_type_info (&info);
8685         return type;
8686 }
8687
8688 /*
8689  * mono_reflection_get_token:
8690  *
8691  *   Return the metadata token of OBJ which should be an object
8692  * representing a metadata element.
8693  */
8694 guint32
8695 mono_reflection_get_token (MonoObject *obj)
8696 {
8697         MonoError error;
8698         MonoClass *klass;
8699         guint32 token = 0;
8700
8701         klass = obj->vtable->klass;
8702
8703         if (strcmp (klass->name, "MethodBuilder") == 0) {
8704                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8705
8706                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8707         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8708                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8709
8710                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8711         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8712                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8713
8714                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8715         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8716                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8717                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8718         } else if (strcmp (klass->name, "MonoType") == 0) {
8719                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8720                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8721                 MonoClass *mc = mono_class_from_mono_type (type);
8722                 if (!mono_class_init (mc))
8723                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8724
8725                 token = mc->type_token;
8726         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8727                    strcmp (klass->name, "MonoMethod") == 0 ||
8728                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8729                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8730                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8731                 if (m->method->is_inflated) {
8732                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8733                         return inflated->declaring->token;
8734                 } else {
8735                         token = m->method->token;
8736                 }
8737         } else if (strcmp (klass->name, "MonoField") == 0) {
8738                 MonoReflectionField *f = (MonoReflectionField*)obj;
8739
8740                 if (is_field_on_inst (f->field)) {
8741                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8742
8743                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8744                                 int field_index = f->field - dgclass->fields;
8745                                 MonoObject *obj;
8746
8747                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8748                                 obj = dgclass->field_objects [field_index];
8749                                 return mono_reflection_get_token (obj);
8750                         }
8751                 }
8752                 token = mono_class_get_field_token (f->field);
8753         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8754                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8755
8756                 token = mono_class_get_property_token (p->property);
8757         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8758                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8759
8760                 token = mono_class_get_event_token (p->event);
8761         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8762                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8763                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8764                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8765
8766                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8767         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8768                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8769
8770                 token = m->token;
8771         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8772                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8773         } else {
8774                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8775                 MonoException *ex = mono_get_exception_not_implemented (msg);
8776                 g_free (msg);
8777                 mono_raise_exception (ex);
8778         }
8779
8780         return token;
8781 }
8782
8783 static MonoClass*
8784 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8785 {
8786         char *n;
8787         MonoType *t;
8788         int slen = mono_metadata_decode_value (p, &p);
8789
8790         mono_error_init (error);
8791
8792         n = (char *)g_memdup (p, slen + 1);
8793         n [slen] = 0;
8794         t = mono_reflection_type_from_name (n, image);
8795         if (!t) {
8796                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8797                 /* We don't free n, it's consumed by mono_error */
8798                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8799                 return NULL;
8800         }
8801         g_free (n);
8802         p += slen;
8803         *end = p;
8804         return mono_class_from_mono_type (t);
8805 }
8806
8807 static void*
8808 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8809 {
8810         int slen, type = t->type;
8811         MonoClass *tklass = t->data.klass;
8812
8813         mono_error_init (error);
8814
8815 handle_enum:
8816         switch (type) {
8817         case MONO_TYPE_U1:
8818         case MONO_TYPE_I1:
8819         case MONO_TYPE_BOOLEAN: {
8820                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8821                 *bval = *p;
8822                 *end = p + 1;
8823                 return bval;
8824         }
8825         case MONO_TYPE_CHAR:
8826         case MONO_TYPE_U2:
8827         case MONO_TYPE_I2: {
8828                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8829                 *val = read16 (p);
8830                 *end = p + 2;
8831                 return val;
8832         }
8833 #if SIZEOF_VOID_P == 4
8834         case MONO_TYPE_U:
8835         case MONO_TYPE_I:
8836 #endif
8837         case MONO_TYPE_R4:
8838         case MONO_TYPE_U4:
8839         case MONO_TYPE_I4: {
8840                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8841                 *val = read32 (p);
8842                 *end = p + 4;
8843                 return val;
8844         }
8845 #if SIZEOF_VOID_P == 8
8846         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8847         case MONO_TYPE_I:
8848 #endif
8849         case MONO_TYPE_U8:
8850         case MONO_TYPE_I8: {
8851                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8852                 *val = read64 (p);
8853                 *end = p + 8;
8854                 return val;
8855         }
8856         case MONO_TYPE_R8: {
8857                 double *val = (double *)g_malloc (sizeof (double));
8858                 readr8 (p, val);
8859                 *end = p + 8;
8860                 return val;
8861         }
8862         case MONO_TYPE_VALUETYPE:
8863                 if (t->data.klass->enumtype) {
8864                         type = mono_class_enum_basetype (t->data.klass)->type;
8865                         goto handle_enum;
8866                 } else {
8867                         MonoClass *k =  t->data.klass;
8868                         
8869                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8870                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8871                                 *val = read64 (p);
8872                                 *end = p + 8;
8873                                 return val;
8874                         }
8875                 }
8876                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8877                 break;
8878                 
8879         case MONO_TYPE_STRING:
8880                 if (*p == (char)0xFF) {
8881                         *end = p + 1;
8882                         return NULL;
8883                 }
8884                 slen = mono_metadata_decode_value (p, &p);
8885                 *end = p + slen;
8886                 return mono_string_new_len (mono_domain_get (), p, slen);
8887         case MONO_TYPE_CLASS: {
8888                 MonoReflectionType *rt;
8889                 char *n;
8890                 MonoType *t;
8891                 if (*p == (char)0xFF) {
8892                         *end = p + 1;
8893                         return NULL;
8894                 }
8895 handle_type:
8896                 slen = mono_metadata_decode_value (p, &p);
8897                 n = (char *)g_memdup (p, slen + 1);
8898                 n [slen] = 0;
8899                 t = mono_reflection_type_from_name (n, image);
8900                 if (!t) {
8901                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8902                         /* We don't free n, it's consumed by mono_error */
8903                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8904                         return NULL;
8905                 }
8906                 g_free (n);
8907                 *end = p + slen;
8908
8909                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8910                 if (!mono_error_ok (error))
8911                         return NULL;
8912
8913                 return rt;
8914         }
8915         case MONO_TYPE_OBJECT: {
8916                 char subt = *p++;
8917                 MonoObject *obj;
8918                 MonoClass *subc = NULL;
8919                 void *val;
8920
8921                 if (subt == 0x50) {
8922                         goto handle_type;
8923                 } else if (subt == 0x0E) {
8924                         type = MONO_TYPE_STRING;
8925                         goto handle_enum;
8926                 } else if (subt == 0x1D) {
8927                         MonoType simple_type = {{0}};
8928                         int etype = *p;
8929                         p ++;
8930
8931                         type = MONO_TYPE_SZARRAY;
8932                         if (etype == 0x50) {
8933                                 tklass = mono_defaults.systemtype_class;
8934                         } else if (etype == 0x55) {
8935                                 tklass = load_cattr_enum_type (image, p, &p, error);
8936                                 if (!mono_error_ok (error))
8937                                         return NULL;
8938                         } else {
8939                                 if (etype == 0x51)
8940                                         /* See Partition II, Appendix B3 */
8941                                         etype = MONO_TYPE_OBJECT;
8942                                 simple_type.type = (MonoTypeEnum)etype;
8943                                 tklass = mono_class_from_mono_type (&simple_type);
8944                         }
8945                         goto handle_enum;
8946                 } else if (subt == 0x55) {
8947                         char *n;
8948                         MonoType *t;
8949                         slen = mono_metadata_decode_value (p, &p);
8950                         n = (char *)g_memdup (p, slen + 1);
8951                         n [slen] = 0;
8952                         t = mono_reflection_type_from_name (n, image);
8953                         if (!t) {
8954                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8955                                 /* We don't free n, it's consumed by mono_error */
8956                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8957                                 return NULL;
8958                         }
8959                         g_free (n);
8960                         p += slen;
8961                         subc = mono_class_from_mono_type (t);
8962                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8963                         MonoType simple_type = {{0}};
8964                         simple_type.type = (MonoTypeEnum)subt;
8965                         subc = mono_class_from_mono_type (&simple_type);
8966                 } else {
8967                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8968                 }
8969                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8970                 obj = NULL;
8971                 if (mono_error_ok (error)) {
8972                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8973                         g_assert (!subc->has_references);
8974                         if (mono_error_ok (error))
8975                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8976                 }
8977
8978                 g_free (val);
8979                 return obj;
8980         }
8981         case MONO_TYPE_SZARRAY: {
8982                 MonoArray *arr;
8983                 guint32 i, alen, basetype;
8984                 alen = read32 (p);
8985                 p += 4;
8986                 if (alen == 0xffffffff) {
8987                         *end = p;
8988                         return NULL;
8989                 }
8990                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8991                 basetype = tklass->byval_arg.type;
8992                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8993                         basetype = mono_class_enum_basetype (tklass)->type;
8994                 switch (basetype)
8995                 {
8996                         case MONO_TYPE_U1:
8997                         case MONO_TYPE_I1:
8998                         case MONO_TYPE_BOOLEAN:
8999                                 for (i = 0; i < alen; i++) {
9000                                         MonoBoolean val = *p++;
9001                                         mono_array_set (arr, MonoBoolean, i, val);
9002                                 }
9003                                 break;
9004                         case MONO_TYPE_CHAR:
9005                         case MONO_TYPE_U2:
9006                         case MONO_TYPE_I2:
9007                                 for (i = 0; i < alen; i++) {
9008                                         guint16 val = read16 (p);
9009                                         mono_array_set (arr, guint16, i, val);
9010                                         p += 2;
9011                                 }
9012                                 break;
9013                         case MONO_TYPE_R4:
9014                         case MONO_TYPE_U4:
9015                         case MONO_TYPE_I4:
9016                                 for (i = 0; i < alen; i++) {
9017                                         guint32 val = read32 (p);
9018                                         mono_array_set (arr, guint32, i, val);
9019                                         p += 4;
9020                                 }
9021                                 break;
9022                         case MONO_TYPE_R8:
9023                                 for (i = 0; i < alen; i++) {
9024                                         double val;
9025                                         readr8 (p, &val);
9026                                         mono_array_set (arr, double, i, val);
9027                                         p += 8;
9028                                 }
9029                                 break;
9030                         case MONO_TYPE_U8:
9031                         case MONO_TYPE_I8:
9032                                 for (i = 0; i < alen; i++) {
9033                                         guint64 val = read64 (p);
9034                                         mono_array_set (arr, guint64, i, val);
9035                                         p += 8;
9036                                 }
9037                                 break;
9038                         case MONO_TYPE_CLASS:
9039                         case MONO_TYPE_OBJECT:
9040                         case MONO_TYPE_STRING:
9041                         case MONO_TYPE_SZARRAY:
9042                                 for (i = 0; i < alen; i++) {
9043                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9044                                         if (!mono_error_ok (error))
9045                                                 return NULL;
9046                                         mono_array_setref (arr, i, item);
9047                                 }
9048                                 break;
9049                         default:
9050                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9051                 }
9052                 *end=p;
9053                 return arr;
9054         }
9055         default:
9056                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9057         }
9058         return NULL;
9059 }
9060
9061 static MonoObject*
9062 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9063 {
9064         static MonoMethod *ctor;
9065         MonoObject *retval;
9066         void *params [2], *unboxed;
9067
9068         mono_error_init (error);
9069
9070         if (!ctor)
9071                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9072         
9073         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9074         return_val_if_nok (error, NULL);
9075
9076         params [1] = val;
9077         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9078         return_val_if_nok (error, NULL);
9079         unboxed = mono_object_unbox (retval);
9080
9081         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9082         return_val_if_nok (error, NULL);
9083
9084         return retval;
9085 }
9086
9087 static MonoObject*
9088 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9089 {
9090         static MonoMethod *ctor;
9091         MonoObject *retval;
9092         void *unboxed, *params [2];
9093
9094         mono_error_init (error);
9095
9096         if (!ctor)
9097                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9098
9099         params [0] = minfo;
9100         params [1] = typedarg;
9101         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9102         return_val_if_nok (error, NULL);
9103
9104         unboxed = mono_object_unbox (retval);
9105
9106         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9107         return_val_if_nok (error, NULL);
9108
9109         return retval;
9110 }
9111
9112 static gboolean
9113 type_is_reference (MonoType *type)
9114 {
9115         switch (type->type) {
9116         case MONO_TYPE_BOOLEAN:
9117         case MONO_TYPE_CHAR:
9118         case MONO_TYPE_U:
9119         case MONO_TYPE_I:
9120         case MONO_TYPE_U1:
9121         case MONO_TYPE_I1:
9122         case MONO_TYPE_U2:
9123         case MONO_TYPE_I2:
9124         case MONO_TYPE_U4:
9125         case MONO_TYPE_I4:
9126         case MONO_TYPE_U8:
9127         case MONO_TYPE_I8:
9128         case MONO_TYPE_R8:
9129         case MONO_TYPE_R4:
9130         case MONO_TYPE_VALUETYPE:
9131                 return FALSE;
9132         default:
9133                 return TRUE;
9134         }
9135 }
9136
9137 static void
9138 free_param_data (MonoMethodSignature *sig, void **params) {
9139         int i;
9140         for (i = 0; i < sig->param_count; ++i) {
9141                 if (!type_is_reference (sig->params [i]))
9142                         g_free (params [i]);
9143         }
9144 }
9145
9146 /*
9147  * Find the field index in the metadata FieldDef table.
9148  */
9149 static guint32
9150 find_field_index (MonoClass *klass, MonoClassField *field) {
9151         int i;
9152
9153         for (i = 0; i < klass->field.count; ++i) {
9154                 if (field == &klass->fields [i])
9155                         return klass->field.first + 1 + i;
9156         }
9157         return 0;
9158 }
9159
9160 /*
9161  * Find the property index in the metadata Property table.
9162  */
9163 static guint32
9164 find_property_index (MonoClass *klass, MonoProperty *property) {
9165         int i;
9166
9167         for (i = 0; i < klass->ext->property.count; ++i) {
9168                 if (property == &klass->ext->properties [i])
9169                         return klass->ext->property.first + 1 + i;
9170         }
9171         return 0;
9172 }
9173
9174 /*
9175  * Find the event index in the metadata Event table.
9176  */
9177 static guint32
9178 find_event_index (MonoClass *klass, MonoEvent *event) {
9179         int i;
9180
9181         for (i = 0; i < klass->ext->event.count; ++i) {
9182                 if (event == &klass->ext->events [i])
9183                         return klass->ext->event.first + 1 + i;
9184         }
9185         return 0;
9186 }
9187
9188 static MonoObject*
9189 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9190 {
9191         const char *p = (const char*)data;
9192         const char *named;
9193         guint32 i, j, num_named;
9194         MonoObject *attr;
9195         void *params_buf [32];
9196         void **params = NULL;
9197         MonoMethodSignature *sig;
9198         MonoObject *exc = NULL;
9199
9200         mono_error_init (error);
9201
9202         mono_class_init (method->klass);
9203
9204         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9205                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9206                 return NULL;
9207         }
9208
9209         if (len == 0) {
9210                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9211                 if (!mono_error_ok (error)) return NULL;
9212
9213                 mono_runtime_invoke_checked (method, attr, NULL, error);
9214                 if (!mono_error_ok (error))
9215                         return NULL;
9216
9217                 return attr;
9218         }
9219
9220         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9221                 return NULL;
9222
9223         /*g_print ("got attr %s\n", method->klass->name);*/
9224
9225         sig = mono_method_signature (method);
9226         if (sig->param_count < 32) {
9227                 params = params_buf;
9228                 memset (params, 0, sizeof (void*) * sig->param_count);
9229         } else {
9230                 /* Allocate using GC so it gets GC tracking */
9231                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9232         }
9233
9234         /* skip prolog */
9235         p += 2;
9236         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9237                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9238                 if (!mono_error_ok (error))
9239                         goto fail;
9240         }
9241
9242         named = p;
9243         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9244         if (!mono_error_ok (error)) goto fail;
9245
9246         mono_runtime_try_invoke (method, attr, params, &exc, error);
9247         if (!mono_error_ok (error))
9248                 goto fail;
9249         if (exc)
9250                 goto fail;
9251
9252         num_named = read16 (named);
9253         named += 2;
9254         for (j = 0; j < num_named; j++) {
9255                 gint name_len;
9256                 char *name, named_type, data_type;
9257                 named_type = *named++;
9258                 data_type = *named++; /* type of data */
9259                 if (data_type == MONO_TYPE_SZARRAY)
9260                         data_type = *named++;
9261                 if (data_type == MONO_TYPE_ENUM) {
9262                         gint type_len;
9263                         char *type_name;
9264                         type_len = mono_metadata_decode_blob_size (named, &named);
9265                         type_name = (char *)g_malloc (type_len + 1);
9266                         memcpy (type_name, named, type_len);
9267                         type_name [type_len] = 0;
9268                         named += type_len;
9269                         /* FIXME: lookup the type and check type consistency */
9270                         g_free (type_name);
9271                 }
9272                 name_len = mono_metadata_decode_blob_size (named, &named);
9273                 name = (char *)g_malloc (name_len + 1);
9274                 memcpy (name, named, name_len);
9275                 name [name_len] = 0;
9276                 named += name_len;
9277                 if (named_type == 0x53) {
9278                         MonoClassField *field;
9279                         void *val;
9280
9281                         /* how this fail is a blackbox */
9282                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9283                         if (!field) {
9284                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9285                                 g_free (name);
9286                                 goto fail;
9287                         }
9288
9289                         val = load_cattr_value (image, field->type, named, &named, error);
9290                         if (!mono_error_ok (error)) {
9291                                 g_free (name);
9292                                 if (!type_is_reference (field->type))
9293                                         g_free (val);
9294                                 goto fail;
9295                         }
9296
9297                         mono_field_set_value (attr, field, val);
9298                         if (!type_is_reference (field->type))
9299                                 g_free (val);
9300                 } else if (named_type == 0x54) {
9301                         MonoProperty *prop;
9302                         void *pparams [1];
9303                         MonoType *prop_type;
9304
9305                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9306
9307                         if (!prop) {
9308                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9309                                 g_free (name);
9310                                 goto fail;
9311                         }
9312
9313                         if (!prop->set) {
9314                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9315                                 g_free (name);
9316                                 goto fail;
9317                         }
9318
9319                         /* can we have more that 1 arg in a custom attr named property? */
9320                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9321                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9322
9323                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9324                         if (!mono_error_ok (error)) {
9325                                 g_free (name);
9326                                 if (!type_is_reference (prop_type))
9327                                         g_free (pparams [0]);
9328                                 goto fail;
9329                         }
9330
9331
9332                         mono_property_set_value (prop, attr, pparams, NULL);
9333                         if (!type_is_reference (prop_type))
9334                                 g_free (pparams [0]);
9335                 }
9336                 g_free (name);
9337         }
9338
9339         free_param_data (method->signature, params);
9340         if (params != params_buf)
9341                 mono_gc_free_fixed (params);
9342
9343         return attr;
9344
9345 fail:
9346         free_param_data (method->signature, params);
9347         if (params != params_buf)
9348                 mono_gc_free_fixed (params);
9349         if (exc)
9350                 mono_raise_exception ((MonoException*)exc);
9351         return NULL;
9352 }
9353         
9354 /*
9355  * mono_reflection_create_custom_attr_data_args:
9356  *
9357  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9358  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9359  * NAMED_ARG_INFO will contain information about the named arguments.
9360  */
9361 void
9362 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)
9363 {
9364         MonoArray *typedargs, *namedargs;
9365         MonoClass *attrklass;
9366         MonoDomain *domain;
9367         const char *p = (const char*)data;
9368         const char *named;
9369         guint32 i, j, num_named;
9370         CattrNamedArg *arginfo = NULL;
9371
9372         *typed_args = NULL;
9373         *named_args = NULL;
9374         *named_arg_info = NULL;
9375
9376         mono_error_init (error);
9377
9378         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9379                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9380                 return;
9381         }
9382
9383         mono_class_init (method->klass);
9384         
9385         domain = mono_domain_get ();
9386
9387         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9388                 return;
9389
9390         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9391         
9392         /* skip prolog */
9393         p += 2;
9394         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9395                 MonoObject *obj;
9396                 void *val;
9397
9398                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9399                 if (!mono_error_ok (error)) {
9400                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9401                                 g_free (val);
9402                         return;
9403                 }
9404
9405                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9406                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9407                 mono_array_setref (typedargs, i, obj);
9408
9409                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9410                         g_free (val);
9411         }
9412
9413         named = p;
9414         num_named = read16 (named);
9415         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9416         named += 2;
9417         attrklass = method->klass;
9418
9419         arginfo = g_new0 (CattrNamedArg, num_named);
9420         *named_arg_info = arginfo;
9421
9422         for (j = 0; j < num_named; j++) {
9423                 gint name_len;
9424                 char *name, named_type, data_type;
9425                 named_type = *named++;
9426                 data_type = *named++; /* type of data */
9427                 if (data_type == MONO_TYPE_SZARRAY)
9428                         data_type = *named++;
9429                 if (data_type == MONO_TYPE_ENUM) {
9430                         gint type_len;
9431                         char *type_name;
9432                         type_len = mono_metadata_decode_blob_size (named, &named);
9433                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9434                                 goto fail;
9435
9436                         type_name = (char *)g_malloc (type_len + 1);
9437                         memcpy (type_name, named, type_len);
9438                         type_name [type_len] = 0;
9439                         named += type_len;
9440                         /* FIXME: lookup the type and check type consistency */
9441                         g_free (type_name);
9442                 }
9443                 name_len = mono_metadata_decode_blob_size (named, &named);
9444                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9445                         goto fail;
9446                 name = (char *)g_malloc (name_len + 1);
9447                 memcpy (name, named, name_len);
9448                 name [name_len] = 0;
9449                 named += name_len;
9450                 if (named_type == 0x53) {
9451                         MonoObject *obj;
9452                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9453                         void *val;
9454
9455                         if (!field) {
9456                                 g_free (name);
9457                                 goto fail;
9458                         }
9459
9460                         arginfo [j].type = field->type;
9461                         arginfo [j].field = field;
9462
9463                         val = load_cattr_value (image, field->type, named, &named, error);
9464                         if (!mono_error_ok (error)) {
9465                                 if (!type_is_reference (field->type))
9466                                         g_free (val);
9467                                 g_free (name);
9468                                 return;
9469                         }
9470
9471                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9472                         mono_array_setref (namedargs, j, obj);
9473                         if (!type_is_reference (field->type))
9474                                 g_free (val);
9475                 } else if (named_type == 0x54) {
9476                         MonoObject *obj;
9477                         MonoType *prop_type;
9478                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9479                         void *val;
9480
9481                         if (!prop || !prop->set) {
9482                                 g_free (name);
9483                                 goto fail;
9484                         }
9485
9486                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9487                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9488
9489                         arginfo [j].type = prop_type;
9490                         arginfo [j].prop = prop;
9491
9492                         val = load_cattr_value (image, prop_type, named, &named, error);
9493                         if (!mono_error_ok (error)) {
9494                                 if (!type_is_reference (prop_type))
9495                                         g_free (val);
9496                                 g_free (name);
9497                                 return;
9498                         }
9499
9500                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9501                         mono_array_setref (namedargs, j, obj);
9502                         if (!type_is_reference (prop_type))
9503                                 g_free (val);
9504                 }
9505                 g_free (name);
9506         }
9507
9508         *typed_args = typedargs;
9509         *named_args = namedargs;
9510         return;
9511 fail:
9512         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9513         g_free (arginfo);
9514         *named_arg_info = NULL;
9515 }
9516
9517 void
9518 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9519 {
9520         MonoDomain *domain;
9521         MonoArray *typedargs, *namedargs;
9522         MonoImage *image;
9523         MonoMethod *method;
9524         CattrNamedArg *arginfo = NULL;
9525         MonoError error;
9526         int i;
9527
9528         mono_error_init (&error);
9529
9530         *ctor_args = NULL;
9531         *named_args = NULL;
9532
9533         if (len == 0)
9534                 return;
9535
9536         image = assembly->assembly->image;
9537         method = ref_method->method;
9538         domain = mono_object_domain (ref_method);
9539
9540         if (!mono_class_init (method->klass))
9541                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9542
9543         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9544         if (!mono_error_ok (&error))
9545                 goto leave;
9546
9547         if (mono_loader_get_last_error ()) {
9548                 mono_error_set_from_loader_error (&error);
9549                 goto leave;
9550         }
9551
9552         if (!typedargs || !namedargs)
9553                 goto leave;
9554
9555         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9556                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9557                 MonoObject *typedarg;
9558
9559                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9560                 if (!is_ok (&error))
9561                         goto leave;
9562                 mono_array_setref (typedargs, i, typedarg);
9563         }
9564
9565         for (i = 0; i < mono_array_length (namedargs); ++i) {
9566                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9567                 MonoObject *typedarg, *namedarg, *minfo;
9568
9569                 if (arginfo [i].prop) {
9570                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9571                         if (!minfo)
9572                                 goto leave;
9573                 } else {
9574                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9575                         if (!mono_error_ok (&error))
9576                                 goto leave;
9577                 }
9578
9579                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9580                 if (!is_ok (&error))
9581                         goto leave;
9582                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9583                 if (!is_ok (&error))
9584                         goto leave;
9585
9586                 mono_array_setref (namedargs, i, namedarg);
9587         }
9588
9589         *ctor_args = typedargs;
9590         *named_args = namedargs;
9591 leave:
9592         g_free (arginfo);
9593         mono_error_raise_exception (&error);
9594
9595 }
9596
9597 static MonoObject*
9598 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9599 {
9600         static MonoMethod *ctor;
9601
9602         MonoDomain *domain;
9603         MonoObject *attr;
9604         void *params [4];
9605
9606         mono_error_init (error);
9607
9608         g_assert (image->assembly);
9609
9610         if (!ctor)
9611                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9612
9613         domain = mono_domain_get ();
9614         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9615         return_val_if_nok (error, NULL);
9616         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9617         return_val_if_nok (error, NULL);
9618         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9619         return_val_if_nok (error, NULL);
9620         params [2] = (gpointer)&cattr->data;
9621         params [3] = &cattr->data_size;
9622
9623         mono_runtime_invoke_checked (ctor, attr, params, error);
9624         return_val_if_nok (error, NULL);
9625         return attr;
9626 }
9627
9628 static MonoArray*
9629 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9630 {
9631         MonoArray *result;
9632         MonoObject *attr;
9633         int i, n;
9634
9635         mono_error_init (error);
9636
9637         n = 0;
9638         for (i = 0; i < cinfo->num_attrs; ++i) {
9639                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9640                         n ++;
9641         }
9642
9643         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9644         n = 0;
9645         for (i = 0; i < cinfo->num_attrs; ++i) {
9646                 if (!cinfo->attrs [i].ctor) {
9647                         /* The cattr type is not finished yet */
9648                         /* We should include the type name but cinfo doesn't contain it */
9649                         mono_error_set_type_load_name (error, NULL, NULL, "");
9650                         return NULL;
9651                 }
9652                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9653                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9654                         if (!mono_error_ok (error))
9655                                 return result;
9656                         mono_array_setref (result, n, attr);
9657                         n ++;
9658                 }
9659         }
9660         return result;
9661 }
9662
9663 MonoArray*
9664 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9665 {
9666         MonoError error;
9667         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9668         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9669
9670         return result;
9671 }
9672
9673 static MonoArray*
9674 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9675 {
9676         MonoArray *result;
9677         MonoObject *attr;
9678         int i;
9679         
9680         mono_error_init (error);
9681         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9682         for (i = 0; i < cinfo->num_attrs; ++i) {
9683                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9684                 return_val_if_nok (error, NULL);
9685                 mono_array_setref (result, i, attr);
9686         }
9687         return result;
9688 }
9689
9690 /**
9691  * mono_custom_attrs_from_index:
9692  *
9693  * Returns: NULL if no attributes are found or if a loading error occurs.
9694  */
9695 MonoCustomAttrInfo*
9696 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9697 {
9698         MonoError error;
9699         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9700         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9701         return result;
9702 }
9703 /**
9704  * mono_custom_attrs_from_index_checked:
9705  *
9706  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9707  */
9708 MonoCustomAttrInfo*
9709 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9710 {
9711         guint32 mtoken, i, len;
9712         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9713         MonoTableInfo *ca;
9714         MonoCustomAttrInfo *ainfo;
9715         GList *tmp, *list = NULL;
9716         const char *data;
9717         MonoCustomAttrEntry* attr;
9718
9719         mono_error_init (error);
9720
9721         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9722
9723         i = mono_metadata_custom_attrs_from_index (image, idx);
9724         if (!i)
9725                 return NULL;
9726         i --;
9727         while (i < ca->rows) {
9728                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9729                         break;
9730                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9731                 ++i;
9732         }
9733         len = g_list_length (list);
9734         if (!len)
9735                 return NULL;
9736         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9737         ainfo->num_attrs = len;
9738         ainfo->image = image;
9739         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9740                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9741                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9742                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9743                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9744                         mtoken |= MONO_TOKEN_METHOD_DEF;
9745                         break;
9746                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9747                         mtoken |= MONO_TOKEN_MEMBER_REF;
9748                         break;
9749                 default:
9750                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9751                         break;
9752                 }
9753                 attr = &ainfo->attrs [i - 1];
9754                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9755                 if (!attr->ctor) {
9756                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9757                         g_list_free (list);
9758                         g_free (ainfo);
9759                         return NULL;
9760                 }
9761
9762                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9763                         /*FIXME raising an exception here doesn't make any sense*/
9764                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9765                         g_list_free (list);
9766                         g_free (ainfo);
9767                         return NULL;
9768                 }
9769                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9770                 attr->data_size = mono_metadata_decode_value (data, &data);
9771                 attr->data = (guchar*)data;
9772         }
9773         g_list_free (list);
9774
9775         return ainfo;
9776 }
9777
9778 MonoCustomAttrInfo*
9779 mono_custom_attrs_from_method (MonoMethod *method)
9780 {
9781         MonoError error;
9782         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9783         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9784         return result;
9785 }
9786
9787 MonoCustomAttrInfo*
9788 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9789 {
9790         guint32 idx;
9791
9792         mono_error_init (error);
9793
9794         /*
9795          * An instantiated method has the same cattrs as the generic method definition.
9796          *
9797          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9798          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9799          */
9800         if (method->is_inflated)
9801                 method = ((MonoMethodInflated *) method)->declaring;
9802         
9803         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9804                 return lookup_custom_attr (method->klass->image, method);
9805
9806         if (!method->token)
9807                 /* Synthetic methods */
9808                 return NULL;
9809
9810         idx = mono_method_get_index (method);
9811         idx <<= MONO_CUSTOM_ATTR_BITS;
9812         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9813         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9814 }
9815
9816 MonoCustomAttrInfo*
9817 mono_custom_attrs_from_class (MonoClass *klass)
9818 {
9819         MonoError error;
9820         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9821         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9822         return result;
9823 }
9824
9825 MonoCustomAttrInfo*
9826 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9827 {
9828         guint32 idx;
9829
9830         mono_error_init (error);
9831
9832         if (klass->generic_class)
9833                 klass = klass->generic_class->container_class;
9834
9835         if (image_is_dynamic (klass->image))
9836                 return lookup_custom_attr (klass->image, klass);
9837
9838         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9839                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9840                 idx <<= MONO_CUSTOM_ATTR_BITS;
9841                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9842         } else {
9843                 idx = mono_metadata_token_index (klass->type_token);
9844                 idx <<= MONO_CUSTOM_ATTR_BITS;
9845                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9846         }
9847         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9848 }
9849
9850 MonoCustomAttrInfo*
9851 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9852 {
9853         MonoError error;
9854         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9855         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9856         return result;
9857 }
9858
9859 MonoCustomAttrInfo*
9860 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9861 {
9862         guint32 idx;
9863         
9864         mono_error_init (error);
9865
9866         if (image_is_dynamic (assembly->image))
9867                 return lookup_custom_attr (assembly->image, assembly);
9868         idx = 1; /* there is only one assembly */
9869         idx <<= MONO_CUSTOM_ATTR_BITS;
9870         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9871         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9872 }
9873
9874 static MonoCustomAttrInfo*
9875 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9876 {
9877         guint32 idx;
9878         
9879         if (image_is_dynamic (image))
9880                 return lookup_custom_attr (image, image);
9881         idx = 1; /* there is only one module */
9882         idx <<= MONO_CUSTOM_ATTR_BITS;
9883         idx |= MONO_CUSTOM_ATTR_MODULE;
9884         return mono_custom_attrs_from_index_checked (image, idx, error);
9885 }
9886
9887 MonoCustomAttrInfo*
9888 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9889 {
9890         MonoError error;
9891         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9892         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9893         return result;
9894 }
9895
9896 MonoCustomAttrInfo*
9897 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9898 {
9899         guint32 idx;
9900         
9901         if (image_is_dynamic (klass->image)) {
9902                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9903                 return lookup_custom_attr (klass->image, property);
9904         }
9905         idx = find_property_index (klass, property);
9906         idx <<= MONO_CUSTOM_ATTR_BITS;
9907         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9908         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9909 }
9910
9911 MonoCustomAttrInfo*
9912 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9913 {
9914         MonoError error;
9915         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9916         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9917         return result;
9918 }
9919
9920 MonoCustomAttrInfo*
9921 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9922 {
9923         guint32 idx;
9924         
9925         if (image_is_dynamic (klass->image)) {
9926                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9927                 return lookup_custom_attr (klass->image, event);
9928         }
9929         idx = find_event_index (klass, event);
9930         idx <<= MONO_CUSTOM_ATTR_BITS;
9931         idx |= MONO_CUSTOM_ATTR_EVENT;
9932         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9933 }
9934
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9937 {
9938         MonoError error;
9939         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9940         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941         return result;
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9946 {
9947         guint32 idx;
9948         mono_error_init (error);
9949
9950         if (image_is_dynamic (klass->image)) {
9951                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9952                 return lookup_custom_attr (klass->image, field);
9953         }
9954         idx = find_field_index (klass, field);
9955         idx <<= MONO_CUSTOM_ATTR_BITS;
9956         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9957         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9958 }
9959
9960 /**
9961  * mono_custom_attrs_from_param:
9962  * @method: handle to the method that we want to retrieve custom parameter information from
9963  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9964  *
9965  * The result must be released with mono_custom_attrs_free().
9966  *
9967  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9968  */
9969 MonoCustomAttrInfo*
9970 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9971 {
9972         MonoError error;
9973         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9974         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9975         return result;
9976 }
9977
9978 /**
9979  * mono_custom_attrs_from_param_checked:
9980  * @method: handle to the method that we want to retrieve custom parameter information from
9981  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9982  * @error: set on error
9983  *
9984  * The result must be released with mono_custom_attrs_free().
9985  *
9986  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9987  */
9988 MonoCustomAttrInfo*
9989 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9990 {
9991         MonoTableInfo *ca;
9992         guint32 i, idx, method_index;
9993         guint32 param_list, param_last, param_pos, found;
9994         MonoImage *image;
9995         MonoReflectionMethodAux *aux;
9996
9997         mono_error_init (error);
9998
9999         /*
10000          * An instantiated method has the same cattrs as the generic method definition.
10001          *
10002          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10003          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10004          */
10005         if (method->is_inflated)
10006                 method = ((MonoMethodInflated *) method)->declaring;
10007
10008         if (image_is_dynamic (method->klass->image)) {
10009                 MonoCustomAttrInfo *res, *ainfo;
10010                 int size;
10011
10012                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10013                 if (!aux || !aux->param_cattr)
10014                         return NULL;
10015
10016                 /* Need to copy since it will be freed later */
10017                 ainfo = aux->param_cattr [param];
10018                 if (!ainfo)
10019                         return NULL;
10020                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10021                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10022                 memcpy (res, ainfo, size);
10023                 return res;
10024         }
10025
10026         image = method->klass->image;
10027         method_index = mono_method_get_index (method);
10028         if (!method_index)
10029                 return NULL;
10030         ca = &image->tables [MONO_TABLE_METHOD];
10031
10032         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10033         if (method_index == ca->rows) {
10034                 ca = &image->tables [MONO_TABLE_PARAM];
10035                 param_last = ca->rows + 1;
10036         } else {
10037                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10038                 ca = &image->tables [MONO_TABLE_PARAM];
10039         }
10040         found = FALSE;
10041         for (i = param_list; i < param_last; ++i) {
10042                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10043                 if (param_pos == param) {
10044                         found = TRUE;
10045                         break;
10046                 }
10047         }
10048         if (!found)
10049                 return NULL;
10050         idx = i;
10051         idx <<= MONO_CUSTOM_ATTR_BITS;
10052         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10053         return mono_custom_attrs_from_index_checked (image, idx, error);
10054 }
10055
10056 gboolean
10057 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10058 {
10059         int i;
10060         MonoClass *klass;
10061         for (i = 0; i < ainfo->num_attrs; ++i) {
10062                 klass = ainfo->attrs [i].ctor->klass;
10063                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10064                         return TRUE;
10065         }
10066         return FALSE;
10067 }
10068
10069 MonoObject*
10070 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10071 {
10072         MonoError error;
10073         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10074         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10075         return res;
10076 }
10077
10078 MonoObject*
10079 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10080 {
10081         int i, attr_index;
10082         MonoClass *klass;
10083         MonoArray *attrs;
10084
10085         mono_error_init (error);
10086
10087         attr_index = -1;
10088         for (i = 0; i < ainfo->num_attrs; ++i) {
10089                 klass = ainfo->attrs [i].ctor->klass;
10090                 if (mono_class_has_parent (klass, attr_klass)) {
10091                         attr_index = i;
10092                         break;
10093                 }
10094         }
10095         if (attr_index == -1)
10096                 return NULL;
10097
10098         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10099         if (!mono_error_ok (error))
10100                 return NULL;
10101         return mono_array_get (attrs, MonoObject*, attr_index);
10102 }
10103
10104 /*
10105  * mono_reflection_get_custom_attrs_info:
10106  * @obj: a reflection object handle
10107  *
10108  * Return the custom attribute info for attributes defined for the
10109  * reflection handle @obj. The objects.
10110  *
10111  * FIXME this function leaks like a sieve for SRE objects.
10112  */
10113 MonoCustomAttrInfo*
10114 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10115 {
10116         MonoError error;
10117         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10118         mono_error_assert_ok (&error);
10119         return result;
10120 }
10121
10122 /**
10123  * mono_reflection_get_custom_attrs_info_checked:
10124  * @obj: a reflection object handle
10125  * @error: set on error
10126  *
10127  * Return the custom attribute info for attributes defined for the
10128  * reflection handle @obj. The objects.
10129  *
10130  * On failure returns NULL and sets @error.
10131  *
10132  * FIXME this function leaks like a sieve for SRE objects.
10133  */
10134 MonoCustomAttrInfo*
10135 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10136 {
10137         MonoClass *klass;
10138         MonoCustomAttrInfo *cinfo = NULL;
10139         
10140         mono_error_init (error);
10141
10142         klass = obj->vtable->klass;
10143         if (klass == mono_defaults.monotype_class) {
10144                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10145                 return_val_if_nok (error, NULL);
10146                 klass = mono_class_from_mono_type (type);
10147                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10148                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10149                 return_val_if_nok (error, NULL);
10150         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10151                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10152                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10153                 return_val_if_nok (error, NULL);
10154         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10155                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10156                 cinfo = mono_custom_attrs_from_module (module->image, error);
10157                 return_val_if_nok (error, NULL);
10158         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10159                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10160                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10161                 return_val_if_nok (error, NULL);
10162         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10163                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10164                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10165                 return_val_if_nok (error, NULL);
10166         } else if (strcmp ("MonoField", klass->name) == 0) {
10167                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10168                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10169                 return_val_if_nok (error, NULL);
10170         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10171                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10172                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10173                 return_val_if_nok (error, NULL);
10174         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10175                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10176                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10177                 return_val_if_nok (error, NULL);
10178         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10179                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10180                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10181                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10182                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10183                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10184                         return_val_if_nok (error, NULL);
10185                 } else if (is_sr_mono_property (member_class)) {
10186                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10187                         MonoMethod *method;
10188                         if (!(method = prop->property->get))
10189                                 method = prop->property->set;
10190                         g_assert (method);
10191
10192                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10193                         return_val_if_nok (error, NULL);
10194                 } 
10195 #ifndef DISABLE_REFLECTION_EMIT
10196                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10197                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10198                         return_val_if_nok (error, NULL);
10199                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10200                         return_val_if_nok (error, NULL);
10201                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10202                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10203                         MonoMethod *method = NULL;
10204                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10205                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10206                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10207                                 method = ((MonoReflectionMethod *)c->cb)->method;
10208                         else
10209                                 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));
10210
10211                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10212                         return_val_if_nok (error, NULL);
10213                 } 
10214 #endif
10215                 else {
10216                         char *type_name = mono_type_get_full_name (member_class);
10217                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10218                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10219                                                       type_name);
10220                         g_free (type_name);
10221                         return NULL;
10222                 }
10223         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10224                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10225                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10226         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10227                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10228                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10229         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10230                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10231                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10232         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10233                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10234                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10235         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10236                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10237                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10238         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10239                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10240                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10241         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10242                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10243                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10244                 return_val_if_nok (error, NULL);
10245         } else { /* handle other types here... */
10246                 g_error ("get custom attrs not yet supported for %s", klass->name);
10247         }
10248
10249         return cinfo;
10250 }
10251
10252 /*
10253  * mono_reflection_get_custom_attrs_by_type:
10254  * @obj: a reflection object handle
10255  *
10256  * Return an array with all the custom attributes defined of the
10257  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10258  * of that type are returned. The objects are fully build. Return NULL if a loading error
10259  * occurs.
10260  */
10261 MonoArray*
10262 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10263 {
10264         MonoArray *result;
10265         MonoCustomAttrInfo *cinfo;
10266
10267         mono_error_init (error);
10268
10269         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10270         return_val_if_nok (error, NULL);
10271         if (cinfo) {
10272                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10273                 if (!result)
10274                         return NULL;
10275                 if (!cinfo->cached)
10276                         mono_custom_attrs_free (cinfo);
10277         } else {
10278                 mono_loader_assert_no_error ();
10279                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10280         }
10281
10282         return result;
10283 }
10284
10285 /*
10286  * mono_reflection_get_custom_attrs:
10287  * @obj: a reflection object handle
10288  *
10289  * Return an array with all the custom attributes defined of the
10290  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10291  * occurs.
10292  */
10293 MonoArray*
10294 mono_reflection_get_custom_attrs (MonoObject *obj)
10295 {
10296         MonoError error;
10297
10298         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10299 }
10300
10301 /*
10302  * mono_reflection_get_custom_attrs_data:
10303  * @obj: a reflection obj handle
10304  *
10305  * Returns an array of System.Reflection.CustomAttributeData,
10306  * which include information about attributes reflected on
10307  * types loaded using the Reflection Only methods
10308  */
10309 MonoArray*
10310 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10311 {
10312         MonoError error;
10313         MonoArray* result;
10314         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10315         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10316         return result;
10317 }
10318
10319 /*
10320  * mono_reflection_get_custom_attrs_data_checked:
10321  * @obj: a reflection obj handle
10322  * @error: set on error
10323  *
10324  * Returns an array of System.Reflection.CustomAttributeData,
10325  * which include information about attributes reflected on
10326  * types loaded using the Reflection Only methods
10327  */
10328 MonoArray*
10329 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10330 {
10331         MonoArray *result;
10332         MonoCustomAttrInfo *cinfo;
10333
10334         mono_error_init (error);
10335
10336         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10337         return_val_if_nok (error, NULL);
10338         if (cinfo) {
10339                 result = mono_custom_attrs_data_construct (cinfo, error);
10340                 return_val_if_nok (error, NULL);
10341                 if (!cinfo->cached)
10342                         mono_custom_attrs_free (cinfo);
10343         } else
10344                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10345
10346         if (mono_loader_get_last_error ())
10347                 mono_error_set_from_loader_error (error);
10348
10349         return result;
10350 }
10351
10352 static MonoReflectionType*
10353 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10354 {
10355         static MonoMethod *method_get_underlying_system_type = NULL;
10356         MonoReflectionType *rt;
10357         MonoMethod *usertype_method;
10358
10359         mono_error_init (error);
10360
10361         if (!method_get_underlying_system_type)
10362                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10363
10364         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10365
10366         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10367
10368         return rt;
10369 }
10370
10371
10372 static gboolean
10373 is_corlib_type (MonoClass *klass)
10374 {
10375         return klass->image == mono_defaults.corlib;
10376 }
10377
10378 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10379         static MonoClass *cached_class; \
10380         if (cached_class) \
10381                 return cached_class == _class; \
10382         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10383                 cached_class = _class; \
10384                 return TRUE; \
10385         } \
10386         return FALSE; \
10387 } while (0) \
10388
10389
10390 #ifndef DISABLE_REFLECTION_EMIT
10391 static gboolean
10392 is_sre_array (MonoClass *klass)
10393 {
10394         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10395 }
10396
10397 static gboolean
10398 is_sre_byref (MonoClass *klass)
10399 {
10400         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10401 }
10402
10403 static gboolean
10404 is_sre_pointer (MonoClass *klass)
10405 {
10406         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10407 }
10408
10409 static gboolean
10410 is_sre_generic_instance (MonoClass *klass)
10411 {
10412         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10413 }
10414
10415 static gboolean
10416 is_sre_type_builder (MonoClass *klass)
10417 {
10418         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10419 }
10420
10421 static gboolean
10422 is_sre_method_builder (MonoClass *klass)
10423 {
10424         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10425 }
10426
10427 static gboolean
10428 is_sre_ctor_builder (MonoClass *klass)
10429 {
10430         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10431 }
10432
10433 static gboolean
10434 is_sre_field_builder (MonoClass *klass)
10435 {
10436         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10437 }
10438
10439 static gboolean
10440 is_sre_method_on_tb_inst (MonoClass *klass)
10441 {
10442         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10443 }
10444
10445 static gboolean
10446 is_sre_ctor_on_tb_inst (MonoClass *klass)
10447 {
10448         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10449 }
10450
10451 MonoType*
10452 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10453 {
10454         MonoClass *klass;
10455         mono_error_init (error);
10456
10457         if (!ref)
10458                 return NULL;
10459         if (ref->type)
10460                 return ref->type;
10461
10462         if (is_usertype (ref)) {
10463                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10464                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10465                         return NULL;
10466                 if (ref->type)
10467                         return ref->type;
10468         }
10469
10470         klass = mono_object_class (ref);
10471
10472         if (is_sre_array (klass)) {
10473                 MonoType *res;
10474                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10475                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10476                 return_val_if_nok (error, NULL);
10477                 g_assert (base);
10478                 if (sre_array->rank == 0) //single dimentional array
10479                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10480                 else
10481                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10482                 sre_array->type.type = res;
10483                 return res;
10484         } else if (is_sre_byref (klass)) {
10485                 MonoType *res;
10486                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10487                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10488                 return_val_if_nok (error, NULL);
10489                 g_assert (base);
10490                 res = &mono_class_from_mono_type (base)->this_arg;
10491                 sre_byref->type.type = res;
10492                 return res;
10493         } else if (is_sre_pointer (klass)) {
10494                 MonoType *res;
10495                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10496                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10497                 return_val_if_nok (error, NULL);
10498                 g_assert (base);
10499                 res = &mono_ptr_class_get (base)->byval_arg;
10500                 sre_pointer->type.type = res;
10501                 return res;
10502         } else if (is_sre_generic_instance (klass)) {
10503                 MonoType *res, **types;
10504                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10505                 int i, count;
10506
10507                 count = mono_array_length (gclass->type_arguments);
10508                 types = g_new0 (MonoType*, count);
10509                 for (i = 0; i < count; ++i) {
10510                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10511                         types [i] = mono_reflection_type_get_handle (t, error);
10512                         if (!types[i] || !is_ok (error)) {
10513                                 g_free (types);
10514                                 return NULL;
10515                         }
10516                 }
10517
10518                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10519                 g_free (types);
10520                 g_assert (res);
10521                 gclass->type.type = res;
10522                 return res;
10523         }
10524
10525         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10526         return NULL;
10527 }
10528
10529 void
10530 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10531 {
10532         MonoError error;
10533         mono_reflection_type_get_handle (type, &error);
10534         mono_error_set_pending_exception (&error);
10535 }
10536
10537 void
10538 mono_reflection_register_with_runtime (MonoReflectionType *type)
10539 {
10540         MonoError error;
10541         MonoType *res = mono_reflection_type_get_handle (type, &error);
10542         mono_error_raise_exception (&error); /* FIXME don't raise here */
10543         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10544         MonoClass *klass;
10545
10546         if (!res)
10547                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10548
10549         klass = mono_class_from_mono_type (res);
10550
10551         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10552         mono_domain_lock (domain);
10553
10554         if (!image_is_dynamic (klass->image)) {
10555                 mono_class_setup_supertypes (klass);
10556         } else {
10557                 if (!domain->type_hash)
10558                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10559                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10560                 mono_g_hash_table_insert (domain->type_hash, res, type);
10561         }
10562         mono_domain_unlock (domain);
10563         mono_loader_unlock ();
10564 }
10565
10566 /**
10567  * LOCKING: Assumes the loader lock is held.
10568  */
10569 static MonoMethodSignature*
10570 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10571         MonoError error;
10572         MonoMethodSignature *sig;
10573         int count, i;
10574
10575         count = parameters? mono_array_length (parameters): 0;
10576
10577         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10578         sig->param_count = count;
10579         sig->sentinelpos = -1; /* FIXME */
10580         for (i = 0; i < count; ++i) {
10581                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10582                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10583         }
10584         return sig;
10585 }
10586
10587 /**
10588  * LOCKING: Assumes the loader lock is held.
10589  */
10590 static MonoMethodSignature*
10591 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10592         MonoMethodSignature *sig;
10593
10594         sig = parameters_to_signature (image, ctor->parameters);
10595         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10596         sig->ret = &mono_defaults.void_class->byval_arg;
10597         return sig;
10598 }
10599
10600 /**
10601  * LOCKING: Assumes the loader lock is held.
10602  */
10603 static MonoMethodSignature*
10604 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10605         MonoError error;
10606         MonoMethodSignature *sig;
10607
10608         sig = parameters_to_signature (image, method->parameters);
10609         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10610         if (method->rtype) {
10611                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10612                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10613         } else {
10614                 sig->ret = &mono_defaults.void_class->byval_arg;
10615         }
10616         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10617         return sig;
10618 }
10619
10620 static MonoMethodSignature*
10621 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10622         MonoError error;
10623         MonoMethodSignature *sig;
10624
10625         sig = parameters_to_signature (NULL, method->parameters);
10626         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10627         if (method->rtype) {
10628                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10629                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10630         } else {
10631                 sig->ret = &mono_defaults.void_class->byval_arg;
10632         }
10633         sig->generic_param_count = 0;
10634         return sig;
10635 }
10636
10637 static void
10638 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10639 {
10640         MonoError error;
10641         MonoClass *klass = mono_object_class (prop);
10642         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10643                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10644                 *name = mono_string_to_utf8 (pb->name);
10645                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10646                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10647         } else {
10648                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10649                 *name = g_strdup (p->property->name);
10650                 if (p->property->get)
10651                         *type = mono_method_signature (p->property->get)->ret;
10652                 else
10653                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10654         }
10655 }
10656
10657 static void
10658 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10659 {
10660         MonoError error;
10661         MonoClass *klass = mono_object_class (field);
10662         if (strcmp (klass->name, "FieldBuilder") == 0) {
10663                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10664                 *name = mono_string_to_utf8 (fb->name);
10665                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10666                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10667         } else {
10668                 MonoReflectionField *f = (MonoReflectionField *)field;
10669                 *name = g_strdup (mono_field_get_name (f->field));
10670                 *type = f->field->type;
10671         }
10672 }
10673
10674 #else /* DISABLE_REFLECTION_EMIT */
10675
10676 void
10677 mono_reflection_register_with_runtime (MonoReflectionType *type)
10678 {
10679         /* This is empty */
10680 }
10681
10682 static gboolean
10683 is_sre_type_builder (MonoClass *klass)
10684 {
10685         return FALSE;
10686 }
10687
10688 static gboolean
10689 is_sre_generic_instance (MonoClass *klass)
10690 {
10691         return FALSE;
10692 }
10693
10694 static void
10695 init_type_builder_generics (MonoObject *type)
10696 {
10697 }
10698
10699 #endif /* !DISABLE_REFLECTION_EMIT */
10700
10701
10702 static gboolean
10703 is_sr_mono_field (MonoClass *klass)
10704 {
10705         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10706 }
10707
10708 static gboolean
10709 is_sr_mono_property (MonoClass *klass)
10710 {
10711         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10712 }
10713
10714 static gboolean
10715 is_sr_mono_method (MonoClass *klass)
10716 {
10717         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10718 }
10719
10720 static gboolean
10721 is_sr_mono_cmethod (MonoClass *klass)
10722 {
10723         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10724 }
10725
10726 static gboolean
10727 is_sr_mono_generic_method (MonoClass *klass)
10728 {
10729         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10730 }
10731
10732 static gboolean
10733 is_sr_mono_generic_cmethod (MonoClass *klass)
10734 {
10735         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10736 }
10737
10738 gboolean
10739 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10740 {
10741         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10742 }
10743
10744 static gboolean
10745 is_usertype (MonoReflectionType *ref)
10746 {
10747         MonoClass *klass = mono_object_class (ref);
10748         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10749 }
10750
10751 static MonoReflectionType*
10752 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10753 {
10754         mono_error_init (error);
10755         if (!type || type->type)
10756                 return type;
10757
10758         if (is_usertype (type)) {
10759                 type = mono_reflection_type_get_underlying_system_type (type, error);
10760                 return_val_if_nok (error, NULL);
10761                 if (is_usertype (type)) {
10762                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10763                         return NULL;
10764                 }
10765         }
10766
10767         return type;
10768 }
10769 /*
10770  * Encode a value in a custom attribute stream of bytes.
10771  * The value to encode is either supplied as an object in argument val
10772  * (valuetypes are boxed), or as a pointer to the data in the
10773  * argument argval.
10774  * @type represents the type of the value
10775  * @buffer is the start of the buffer
10776  * @p the current position in the buffer
10777  * @buflen contains the size of the buffer and is used to return the new buffer size
10778  * if this needs to be realloced.
10779  * @retbuffer and @retp return the start and the position of the buffer
10780  */
10781 static void
10782 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10783 {
10784         MonoError error;
10785         MonoTypeEnum simple_type;
10786         
10787         if ((p-buffer) + 10 >= *buflen) {
10788                 char *newbuf;
10789                 *buflen *= 2;
10790                 newbuf = (char *)g_realloc (buffer, *buflen);
10791                 p = newbuf + (p-buffer);
10792                 buffer = newbuf;
10793         }
10794         if (!argval)
10795                 argval = ((char*)arg + sizeof (MonoObject));
10796         simple_type = type->type;
10797 handle_enum:
10798         switch (simple_type) {
10799         case MONO_TYPE_BOOLEAN:
10800         case MONO_TYPE_U1:
10801         case MONO_TYPE_I1:
10802                 *p++ = *argval;
10803                 break;
10804         case MONO_TYPE_CHAR:
10805         case MONO_TYPE_U2:
10806         case MONO_TYPE_I2:
10807                 swap_with_size (p, argval, 2, 1);
10808                 p += 2;
10809                 break;
10810         case MONO_TYPE_U4:
10811         case MONO_TYPE_I4:
10812         case MONO_TYPE_R4:
10813                 swap_with_size (p, argval, 4, 1);
10814                 p += 4;
10815                 break;
10816         case MONO_TYPE_R8:
10817                 swap_with_size (p, argval, 8, 1);
10818                 p += 8;
10819                 break;
10820         case MONO_TYPE_U8:
10821         case MONO_TYPE_I8:
10822                 swap_with_size (p, argval, 8, 1);
10823                 p += 8;
10824                 break;
10825         case MONO_TYPE_VALUETYPE:
10826                 if (type->data.klass->enumtype) {
10827                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10828                         goto handle_enum;
10829                 } else {
10830                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10831                 }
10832                 break;
10833         case MONO_TYPE_STRING: {
10834                 char *str;
10835                 guint32 slen;
10836                 if (!arg) {
10837                         *p++ = 0xFF;
10838                         break;
10839                 }
10840                 str = mono_string_to_utf8 ((MonoString*)arg);
10841                 slen = strlen (str);
10842                 if ((p-buffer) + 10 + slen >= *buflen) {
10843                         char *newbuf;
10844                         *buflen *= 2;
10845                         *buflen += slen;
10846                         newbuf = (char *)g_realloc (buffer, *buflen);
10847                         p = newbuf + (p-buffer);
10848                         buffer = newbuf;
10849                 }
10850                 mono_metadata_encode_value (slen, p, &p);
10851                 memcpy (p, str, slen);
10852                 p += slen;
10853                 g_free (str);
10854                 break;
10855         }
10856         case MONO_TYPE_CLASS: {
10857                 char *str;
10858                 guint32 slen;
10859                 MonoType *arg_type;
10860                 if (!arg) {
10861                         *p++ = 0xFF;
10862                         break;
10863                 }
10864 handle_type:
10865                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10866                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10867                 str = type_get_qualified_name (arg_type, NULL);
10868                 slen = strlen (str);
10869                 if ((p-buffer) + 10 + slen >= *buflen) {
10870                         char *newbuf;
10871                         *buflen *= 2;
10872                         *buflen += slen;
10873                         newbuf = (char *)g_realloc (buffer, *buflen);
10874                         p = newbuf + (p-buffer);
10875                         buffer = newbuf;
10876                 }
10877                 mono_metadata_encode_value (slen, p, &p);
10878                 memcpy (p, str, slen);
10879                 p += slen;
10880                 g_free (str);
10881                 break;
10882         }
10883         case MONO_TYPE_SZARRAY: {
10884                 int len, i;
10885                 MonoClass *eclass, *arg_eclass;
10886
10887                 if (!arg) {
10888                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10889                         break;
10890                 }
10891                 len = mono_array_length ((MonoArray*)arg);
10892                 *p++ = len & 0xff;
10893                 *p++ = (len >> 8) & 0xff;
10894                 *p++ = (len >> 16) & 0xff;
10895                 *p++ = (len >> 24) & 0xff;
10896                 *retp = p;
10897                 *retbuffer = buffer;
10898                 eclass = type->data.klass;
10899                 arg_eclass = mono_object_class (arg)->element_class;
10900
10901                 if (!eclass) {
10902                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10903                         eclass = mono_defaults.object_class;
10904                 }
10905                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10906                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10907                         int elsize = mono_class_array_element_size (arg_eclass);
10908                         for (i = 0; i < len; ++i) {
10909                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10910                                 elptr += elsize;
10911                         }
10912                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10913                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10914                         int elsize = mono_class_array_element_size (eclass);
10915                         for (i = 0; i < len; ++i) {
10916                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10917                                 elptr += elsize;
10918                         }
10919                 } else {
10920                         for (i = 0; i < len; ++i) {
10921                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10922                         }
10923                 }
10924                 break;
10925         }
10926         case MONO_TYPE_OBJECT: {
10927                 MonoClass *klass;
10928                 char *str;
10929                 guint32 slen;
10930
10931                 /*
10932                  * The parameter type is 'object' but the type of the actual
10933                  * argument is not. So we have to add type information to the blob
10934                  * too. This is completely undocumented in the spec.
10935                  */
10936
10937                 if (arg == NULL) {
10938                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10939                         *p++ = 0xFF;
10940                         break;
10941                 }
10942                 
10943                 klass = mono_object_class (arg);
10944
10945                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10946                         *p++ = 0x50;
10947                         goto handle_type;
10948                 } else if (klass->enumtype) {
10949                         *p++ = 0x55;
10950                 } else if (klass == mono_defaults.string_class) {
10951                         simple_type = MONO_TYPE_STRING;
10952                         *p++ = 0x0E;
10953                         goto handle_enum;
10954                 } else if (klass->rank == 1) {
10955                         *p++ = 0x1D;
10956                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10957                                 /* See Partition II, Appendix B3 */
10958                                 *p++ = 0x51;
10959                         else
10960                                 *p++ = klass->element_class->byval_arg.type;
10961                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10962                         break;
10963                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10964                         *p++ = simple_type = klass->byval_arg.type;
10965                         goto handle_enum;
10966                 } else {
10967                         g_error ("unhandled type in custom attr");
10968                 }
10969                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10970                 slen = strlen (str);
10971                 if ((p-buffer) + 10 + slen >= *buflen) {
10972                         char *newbuf;
10973                         *buflen *= 2;
10974                         *buflen += slen;
10975                         newbuf = (char *)g_realloc (buffer, *buflen);
10976                         p = newbuf + (p-buffer);
10977                         buffer = newbuf;
10978                 }
10979                 mono_metadata_encode_value (slen, p, &p);
10980                 memcpy (p, str, slen);
10981                 p += slen;
10982                 g_free (str);
10983                 simple_type = mono_class_enum_basetype (klass)->type;
10984                 goto handle_enum;
10985         }
10986         default:
10987                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10988         }
10989         *retp = p;
10990         *retbuffer = buffer;
10991 }
10992
10993 static void
10994 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10995 {
10996         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10997                 char *str = type_get_qualified_name (type, NULL);
10998                 int slen = strlen (str);
10999
11000                 *p++ = 0x55;
11001                 /*
11002                  * This seems to be optional...
11003                  * *p++ = 0x80;
11004                  */
11005                 mono_metadata_encode_value (slen, p, &p);
11006                 memcpy (p, str, slen);
11007                 p += slen;
11008                 g_free (str);
11009         } else if (type->type == MONO_TYPE_OBJECT) {
11010                 *p++ = 0x51;
11011         } else if (type->type == MONO_TYPE_CLASS) {
11012                 /* it should be a type: encode_cattr_value () has the check */
11013                 *p++ = 0x50;
11014         } else {
11015                 mono_metadata_encode_value (type->type, p, &p);
11016                 if (type->type == MONO_TYPE_SZARRAY)
11017                         /* See the examples in Partition VI, Annex B */
11018                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11019         }
11020
11021         *retp = p;
11022 }
11023
11024 #ifndef DISABLE_REFLECTION_EMIT
11025 static void
11026 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11027 {
11028         int len;
11029         /* Preallocate a large enough buffer */
11030         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11031                 char *str = type_get_qualified_name (type, NULL);
11032                 len = strlen (str);
11033                 g_free (str);
11034         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11035                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11036                 len = strlen (str);
11037                 g_free (str);
11038         } else {
11039                 len = 0;
11040         }
11041         len += strlen (name);
11042
11043         if ((p-buffer) + 20 + len >= *buflen) {
11044                 char *newbuf;
11045                 *buflen *= 2;
11046                 *buflen += len;
11047                 newbuf = (char *)g_realloc (buffer, *buflen);
11048                 p = newbuf + (p-buffer);
11049                 buffer = newbuf;
11050         }
11051
11052         encode_field_or_prop_type (type, p, &p);
11053
11054         len = strlen (name);
11055         mono_metadata_encode_value (len, p, &p);
11056         memcpy (p, name, len);
11057         p += len;
11058         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11059         *retp = p;
11060         *retbuffer = buffer;
11061 }
11062
11063 /*
11064  * mono_reflection_get_custom_attrs_blob:
11065  * @ctor: custom attribute constructor
11066  * @ctorArgs: arguments o the constructor
11067  * @properties:
11068  * @propValues:
11069  * @fields:
11070  * @fieldValues:
11071  * 
11072  * Creates the blob of data that needs to be saved in the metadata and that represents
11073  * the custom attributed described by @ctor, @ctorArgs etc.
11074  * Returns: a Byte array representing the blob of data.
11075  */
11076 MonoArray*
11077 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11078 {
11079         MonoArray *result;
11080         MonoMethodSignature *sig;
11081         MonoObject *arg;
11082         char *buffer, *p;
11083         guint32 buflen, i;
11084
11085         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11086                 /* sig is freed later so allocate it in the heap */
11087                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11088         } else {
11089                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11090         }
11091
11092         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11093         buflen = 256;
11094         p = buffer = (char *)g_malloc (buflen);
11095         /* write the prolog */
11096         *p++ = 1;
11097         *p++ = 0;
11098         for (i = 0; i < sig->param_count; ++i) {
11099                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11100                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11101         }
11102         i = 0;
11103         if (properties)
11104                 i += mono_array_length (properties);
11105         if (fields)
11106                 i += mono_array_length (fields);
11107         *p++ = i & 0xff;
11108         *p++ = (i >> 8) & 0xff;
11109         if (properties) {
11110                 MonoObject *prop;
11111                 for (i = 0; i < mono_array_length (properties); ++i) {
11112                         MonoType *ptype;
11113                         char *pname;
11114
11115                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11116                         get_prop_name_and_type (prop, &pname, &ptype);
11117                         *p++ = 0x54; /* PROPERTY signature */
11118                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11119                         g_free (pname);
11120                 }
11121         }
11122
11123         if (fields) {
11124                 MonoObject *field;
11125                 for (i = 0; i < mono_array_length (fields); ++i) {
11126                         MonoType *ftype;
11127                         char *fname;
11128
11129                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11130                         get_field_name_and_type (field, &fname, &ftype);
11131                         *p++ = 0x53; /* FIELD signature */
11132                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11133                         g_free (fname);
11134                 }
11135         }
11136
11137         g_assert (p - buffer <= buflen);
11138         buflen = p - buffer;
11139         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11140         p = mono_array_addr (result, char, 0);
11141         memcpy (p, buffer, buflen);
11142         g_free (buffer);
11143         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11144                 g_free (sig);
11145         return result;
11146 }
11147
11148 /*
11149  * mono_reflection_setup_internal_class:
11150  * @tb: a TypeBuilder object
11151  *
11152  * Creates a MonoClass that represents the TypeBuilder.
11153  * This is a trick that lets us simplify a lot of reflection code
11154  * (and will allow us to support Build and Run assemblies easier).
11155  */
11156 void
11157 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11158 {
11159         MonoError error;
11160         MonoClass *klass, *parent;
11161
11162         RESOLVE_TYPE (tb->parent, &error);
11163         mono_error_raise_exception (&error); /* FIXME don't raise here */
11164
11165         mono_loader_lock ();
11166
11167         if (tb->parent) {
11168                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11169                 if (!is_ok (&error)) {
11170                         mono_loader_unlock ();
11171                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11172                 }
11173                 /* check so we can compile corlib correctly */
11174                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11175                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11176                         parent = parent_type->data.klass;
11177                 } else {
11178                         parent = mono_class_from_mono_type (parent_type);
11179                 }
11180         } else {
11181                 parent = NULL;
11182         }
11183         
11184         /* the type has already being created: it means we just have to change the parent */
11185         if (tb->type.type) {
11186                 klass = mono_class_from_mono_type (tb->type.type);
11187                 klass->parent = NULL;
11188                 /* fool mono_class_setup_parent */
11189                 klass->supertypes = NULL;
11190                 mono_class_setup_parent (klass, parent);
11191                 mono_class_setup_mono_type (klass);
11192                 mono_loader_unlock ();
11193                 return;
11194         }
11195
11196         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11197
11198         klass->image = &tb->module->dynamic_image->image;
11199
11200         klass->inited = 1; /* we lie to the runtime */
11201         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11202         if (!mono_error_ok (&error))
11203                 goto failure;
11204         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11205         if (!mono_error_ok (&error))
11206                 goto failure;
11207         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11208         klass->flags = tb->attrs;
11209         
11210         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11211
11212         klass->element_class = klass;
11213
11214         if (mono_class_get_ref_info (klass) == NULL) {
11215
11216                 mono_class_set_ref_info (klass, tb);
11217
11218                 /* Put into cache so mono_class_get_checked () will find it.
11219                 Skip nested types as those should not be available on the global scope. */
11220                 if (!tb->nesting_type)
11221                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11222
11223                 /*
11224                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11225                 by performing a mono_class_get which does the full resolution.
11226
11227                 Working around this semantics would require us to write a lot of code for no clear advantage.
11228                 */
11229                 mono_image_append_class_to_reflection_info_set (klass);
11230         } else {
11231                 g_assert (mono_class_get_ref_info (klass) == tb);
11232         }
11233
11234         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11235
11236         if (parent != NULL) {
11237                 mono_class_setup_parent (klass, parent);
11238         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11239                 const char *old_n = klass->name;
11240                 /* trick to get relative numbering right when compiling corlib */
11241                 klass->name = "BuildingObject";
11242                 mono_class_setup_parent (klass, mono_defaults.object_class);
11243                 klass->name = old_n;
11244         }
11245
11246         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11247                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11248                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11249                 klass->instance_size = sizeof (MonoObject);
11250                 klass->size_inited = 1;
11251                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11252         }
11253
11254         mono_class_setup_mono_type (klass);
11255
11256         mono_class_setup_supertypes (klass);
11257
11258         /*
11259          * FIXME: handle interfaces.
11260          */
11261
11262         tb->type.type = &klass->byval_arg;
11263
11264         if (tb->nesting_type) {
11265                 g_assert (tb->nesting_type->type);
11266                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11267                 if (!is_ok (&error)) goto failure;
11268                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11269         }
11270
11271         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11272
11273         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11274         
11275         mono_loader_unlock ();
11276         return;
11277
11278 failure:
11279         mono_loader_unlock ();
11280         mono_error_raise_exception (&error);
11281 }
11282
11283 /*
11284  * mono_reflection_setup_generic_class:
11285  * @tb: a TypeBuilder object
11286  *
11287  * Setup the generic class before adding the first generic parameter.
11288  */
11289 void
11290 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11291 {
11292 }
11293
11294 /*
11295  * mono_reflection_create_generic_class:
11296  * @tb: a TypeBuilder object
11297  *
11298  * Creates the generic class after all generic parameters have been added.
11299  */
11300 void
11301 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11302 {
11303         MonoError error;
11304         MonoClass *klass;
11305         int count, i;
11306
11307         klass = mono_class_from_mono_type (tb->type.type);
11308
11309         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11310
11311         if (klass->generic_container || (count == 0))
11312                 return;
11313
11314         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11315
11316         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11317
11318         klass->generic_container->owner.klass = klass;
11319         klass->generic_container->type_argc = count;
11320         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11321
11322         klass->is_generic = 1;
11323
11324         for (i = 0; i < count; i++) {
11325                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11326                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11327                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11328                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11329                 klass->generic_container->type_params [i] = *param;
11330                 /*Make sure we are a diferent type instance */
11331                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11332                 klass->generic_container->type_params [i].info.pklass = NULL;
11333                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11334
11335                 g_assert (klass->generic_container->type_params [i].param.owner);
11336         }
11337
11338         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11339 }
11340
11341 /*
11342  * mono_reflection_create_internal_class:
11343  * @tb: a TypeBuilder object
11344  *
11345  * Actually create the MonoClass that is associated with the TypeBuilder.
11346  */
11347 void
11348 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11349 {
11350         MonoError error;
11351         MonoClass *klass;
11352
11353         klass = mono_class_from_mono_type (tb->type.type);
11354
11355         mono_loader_lock ();
11356         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11357                 MonoReflectionFieldBuilder *fb;
11358                 MonoClass *ec;
11359                 MonoType *enum_basetype;
11360
11361                 g_assert (tb->fields != NULL);
11362                 g_assert (mono_array_length (tb->fields) >= 1);
11363
11364                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11365
11366                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11367                 if (!is_ok (&error)) {
11368                         mono_loader_unlock ();
11369                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11370                 }
11371                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11372                         mono_loader_unlock ();
11373                         return;
11374                 }
11375
11376                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11377                 if (!is_ok (&error)) {
11378                         mono_loader_unlock ();
11379                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11380                 }
11381                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11382                 if (!klass->element_class)
11383                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11384
11385                 /*
11386                  * get the element_class from the current corlib.
11387                  */
11388                 ec = default_class_from_mono_type (enum_basetype);
11389                 klass->instance_size = ec->instance_size;
11390                 klass->size_inited = 1;
11391                 /* 
11392                  * this is almost safe to do with enums and it's needed to be able
11393                  * to create objects of the enum type (for use in SetConstant).
11394                  */
11395                 /* FIXME: Does this mean enums can't have method overrides ? */
11396                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11397         }
11398         mono_loader_unlock ();
11399 }
11400
11401 static MonoMarshalSpec*
11402 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11403                                                                 MonoReflectionMarshal *minfo)
11404 {
11405         MonoError error;
11406         MonoMarshalSpec *res;
11407
11408         res = image_g_new0 (image, MonoMarshalSpec, 1);
11409         res->native = (MonoMarshalNative)minfo->type;
11410
11411         switch (minfo->type) {
11412         case MONO_NATIVE_LPARRAY:
11413                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11414                 if (minfo->has_size) {
11415                         res->data.array_data.param_num = minfo->param_num;
11416                         res->data.array_data.num_elem = minfo->count;
11417                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11418                 }
11419                 else {
11420                         res->data.array_data.param_num = -1;
11421                         res->data.array_data.num_elem = -1;
11422                         res->data.array_data.elem_mult = -1;
11423                 }
11424                 break;
11425
11426         case MONO_NATIVE_BYVALTSTR:
11427         case MONO_NATIVE_BYVALARRAY:
11428                 res->data.array_data.num_elem = minfo->count;
11429                 break;
11430
11431         case MONO_NATIVE_CUSTOM:
11432                 if (minfo->marshaltyperef) {
11433                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11434                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11435                         res->data.custom_data.custom_name =
11436                                 type_get_fully_qualified_name (marshaltyperef);
11437                 }
11438                 if (minfo->mcookie)
11439                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11440                 break;
11441
11442         default:
11443                 break;
11444         }
11445
11446         return res;
11447 }
11448 #endif /* !DISABLE_REFLECTION_EMIT */
11449
11450 MonoReflectionMarshalAsAttribute*
11451 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11452                                                         MonoMarshalSpec *spec, MonoError *error)
11453 {
11454         MonoReflectionType *rt;
11455         MonoReflectionMarshalAsAttribute *minfo;
11456         MonoType *mtype;
11457
11458         mono_error_init (error);
11459         
11460         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11461         if (!minfo)
11462                 return NULL;
11463         minfo->utype = spec->native;
11464
11465         switch (minfo->utype) {
11466         case MONO_NATIVE_LPARRAY:
11467                 minfo->array_subtype = spec->data.array_data.elem_type;
11468                 minfo->size_const = spec->data.array_data.num_elem;
11469                 if (spec->data.array_data.param_num != -1)
11470                         minfo->size_param_index = spec->data.array_data.param_num;
11471                 break;
11472
11473         case MONO_NATIVE_BYVALTSTR:
11474         case MONO_NATIVE_BYVALARRAY:
11475                 minfo->size_const = spec->data.array_data.num_elem;
11476                 break;
11477
11478         case MONO_NATIVE_CUSTOM:
11479                 if (spec->data.custom_data.custom_name) {
11480                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11481                         if (mtype) {
11482                                 rt = mono_type_get_object_checked (domain, mtype, error);
11483                                 if (!rt)
11484                                         return NULL;
11485
11486                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11487                         }
11488
11489                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11490                 }
11491                 if (spec->data.custom_data.cookie)
11492                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11493                 break;
11494
11495         default:
11496                 break;
11497         }
11498
11499         return minfo;
11500 }
11501
11502 #ifndef DISABLE_REFLECTION_EMIT
11503 static MonoMethod*
11504 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11505                                          ReflectionMethodBuilder *rmb,
11506                                          MonoMethodSignature *sig)
11507 {
11508         MonoError error;
11509         MonoMethod *m;
11510         MonoMethodWrapper *wrapperm;
11511         MonoMarshalSpec **specs;
11512         MonoReflectionMethodAux *method_aux;
11513         MonoImage *image;
11514         gboolean dynamic;
11515         int i;
11516
11517         mono_error_init (&error);
11518         /*
11519          * Methods created using a MethodBuilder should have their memory allocated
11520          * inside the image mempool, while dynamic methods should have their memory
11521          * malloc'd.
11522          */
11523         dynamic = rmb->refs != NULL;
11524         image = dynamic ? NULL : klass->image;
11525
11526         if (!dynamic)
11527                 g_assert (!klass->generic_class);
11528
11529         mono_loader_lock ();
11530
11531         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11532                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11533                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11534         else
11535                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11536
11537         wrapperm = (MonoMethodWrapper*)m;
11538
11539         m->dynamic = dynamic;
11540         m->slot = -1;
11541         m->flags = rmb->attrs;
11542         m->iflags = rmb->iattrs;
11543         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11544         m->klass = klass;
11545         m->signature = sig;
11546         m->sre_method = TRUE;
11547         m->skip_visibility = rmb->skip_visibility;
11548         if (rmb->table_idx)
11549                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11550
11551         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11552                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11553                         m->string_ctor = 1;
11554
11555                 m->signature->pinvoke = 1;
11556         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11557                 m->signature->pinvoke = 1;
11558
11559                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11560
11561                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11562                 g_assert (mono_error_ok (&error));
11563                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11564                 g_assert (mono_error_ok (&error));
11565                 
11566                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11567
11568                 if (image_is_dynamic (klass->image))
11569                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11570
11571                 mono_loader_unlock ();
11572
11573                 return m;
11574         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11575                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11576                 MonoMethodHeader *header;
11577                 guint32 code_size;
11578                 gint32 max_stack, i;
11579                 gint32 num_locals = 0;
11580                 gint32 num_clauses = 0;
11581                 guint8 *code;
11582
11583                 if (rmb->ilgen) {
11584                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11585                         code_size = rmb->ilgen->code_len;
11586                         max_stack = rmb->ilgen->max_stack;
11587                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11588                         if (rmb->ilgen->ex_handlers)
11589                                 num_clauses = method_count_clauses (rmb->ilgen);
11590                 } else {
11591                         if (rmb->code) {
11592                                 code = mono_array_addr (rmb->code, guint8, 0);
11593                                 code_size = mono_array_length (rmb->code);
11594                                 /* we probably need to run a verifier on the code... */
11595                                 max_stack = 8; 
11596                         }
11597                         else {
11598                                 code = NULL;
11599                                 code_size = 0;
11600                                 max_stack = 8;
11601                         }
11602                 }
11603
11604                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11605                 header->code_size = code_size;
11606                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11607                 memcpy ((char*)header->code, code, code_size);
11608                 header->max_stack = max_stack;
11609                 header->init_locals = rmb->init_locals;
11610                 header->num_locals = num_locals;
11611
11612                 for (i = 0; i < num_locals; ++i) {
11613                         MonoReflectionLocalBuilder *lb = 
11614                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11615
11616                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11617                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11618                         mono_error_assert_ok (&error);
11619                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11620                 }
11621
11622                 header->num_clauses = num_clauses;
11623                 if (num_clauses) {
11624                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11625                                                                  rmb->ilgen, num_clauses, &error);
11626                         mono_error_assert_ok (&error);
11627                 }
11628
11629                 wrapperm->header = header;
11630         }
11631
11632         if (rmb->generic_params) {
11633                 int count = mono_array_length (rmb->generic_params);
11634                 MonoGenericContainer *container = rmb->generic_container;
11635
11636                 g_assert (container);
11637
11638                 container->type_argc = count;
11639                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11640                 container->owner.method = m;
11641                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11642
11643                 m->is_generic = TRUE;
11644                 mono_method_set_generic_container (m, container);
11645
11646                 for (i = 0; i < count; i++) {
11647                         MonoReflectionGenericParam *gp =
11648                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11649                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11650                         mono_error_assert_ok (&error);
11651                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11652                         container->type_params [i] = *param;
11653                 }
11654
11655                 /*
11656                  * The method signature might have pointers to generic parameters that belong to other methods.
11657                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11658                  * generic parameters.
11659                  */
11660                 for (i = 0; i < m->signature->param_count; ++i) {
11661                         MonoType *t = m->signature->params [i];
11662                         if (t->type == MONO_TYPE_MVAR) {
11663                                 MonoGenericParam *gparam =  t->data.generic_param;
11664                                 if (gparam->num < count) {
11665                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11666                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11667                                 }
11668
11669                         }
11670                 }
11671
11672                 if (klass->generic_container) {
11673                         container->parent = klass->generic_container;
11674                         container->context.class_inst = klass->generic_container->context.class_inst;
11675                 }
11676                 container->context.method_inst = mono_get_shared_generic_inst (container);
11677         }
11678
11679         if (rmb->refs) {
11680                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11681                 int i;
11682                 void **data;
11683
11684                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11685
11686                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11687                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11688                 for (i = 0; i < rmb->nrefs; ++i)
11689                         data [i + 1] = rmb->refs [i];
11690         }
11691
11692         method_aux = NULL;
11693
11694         /* Parameter info */
11695         if (rmb->pinfo) {
11696                 if (!method_aux)
11697                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11698                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11699                 for (i = 0; i <= m->signature->param_count; ++i) {
11700                         MonoReflectionParamBuilder *pb;
11701                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11702                                 if ((i > 0) && (pb->attrs)) {
11703                                         /* Make a copy since it might point to a shared type structure */
11704                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11705                                         m->signature->params [i - 1]->attrs = pb->attrs;
11706                                 }
11707
11708                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11709                                         MonoDynamicImage *assembly;
11710                                         guint32 idx, len;
11711                                         MonoTypeEnum def_type;
11712                                         char *p;
11713                                         const char *p2;
11714
11715                                         if (!method_aux->param_defaults) {
11716                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11717                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11718                                         }
11719                                         assembly = (MonoDynamicImage*)klass->image;
11720                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11721                                         /* Copy the data from the blob since it might get realloc-ed */
11722                                         p = assembly->blob.data + idx;
11723                                         len = mono_metadata_decode_blob_size (p, &p2);
11724                                         len += p2 - p;
11725                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11726                                         method_aux->param_default_types [i] = def_type;
11727                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11728                                 }
11729
11730                                 if (pb->name) {
11731                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11732                                         g_assert (mono_error_ok (&error));
11733                                 }
11734                                 if (pb->cattrs) {
11735                                         if (!method_aux->param_cattr)
11736                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11737                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11738                                 }
11739                         }
11740                 }
11741         }
11742
11743         /* Parameter marshalling */
11744         specs = NULL;
11745         if (rmb->pinfo)         
11746                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11747                         MonoReflectionParamBuilder *pb;
11748                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11749                                 if (pb->marshal_info) {
11750                                         if (specs == NULL)
11751                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11752                                         specs [pb->position] = 
11753                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11754                                 }
11755                         }
11756                 }
11757         if (specs != NULL) {
11758                 if (!method_aux)
11759                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11760                 method_aux->param_marshall = specs;
11761         }
11762
11763         if (image_is_dynamic (klass->image) && method_aux)
11764                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11765
11766         mono_loader_unlock ();
11767
11768         return m;
11769 }       
11770
11771 static MonoMethod*
11772 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11773 {
11774         ReflectionMethodBuilder rmb;
11775         MonoMethodSignature *sig;
11776
11777         mono_loader_lock ();
11778         sig = ctor_builder_to_signature (klass->image, mb);
11779         mono_loader_unlock ();
11780
11781         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11782                 return NULL;
11783
11784         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11785         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11786
11787         /* If we are in a generic class, we might be called multiple times from inflate_method */
11788         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11789                 /* ilgen is no longer needed */
11790                 mb->ilgen = NULL;
11791         }
11792
11793         return mb->mhandle;
11794 }
11795
11796 static MonoMethod*
11797 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11798 {
11799         ReflectionMethodBuilder rmb;
11800         MonoMethodSignature *sig;
11801
11802         mono_error_init (error);
11803
11804         mono_loader_lock ();
11805         sig = method_builder_to_signature (klass->image, mb);
11806         mono_loader_unlock ();
11807
11808         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11809                 return NULL;
11810
11811         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11812         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11813
11814         /* If we are in a generic class, we might be called multiple times from inflate_method */
11815         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11816                 /* ilgen is no longer needed */
11817                 mb->ilgen = NULL;
11818         }
11819         return mb->mhandle;
11820 }
11821
11822 static MonoClassField*
11823 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11824 {
11825         MonoClassField *field;
11826         MonoType *custom;
11827         MonoError error;
11828
11829         field = g_new0 (MonoClassField, 1);
11830
11831         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11832         g_assert (mono_error_ok (&error));
11833         if (fb->attrs || fb->modreq || fb->modopt) {
11834                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11835                 if (!is_ok (&error)) {
11836                         g_free (field);
11837                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11838                 }
11839                 field->type = mono_metadata_type_dup (NULL, type);
11840                 field->type->attrs = fb->attrs;
11841
11842                 g_assert (image_is_dynamic (klass->image));
11843                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11844                 g_free (field->type);
11845                 field->type = mono_metadata_type_dup (klass->image, custom);
11846                 g_free (custom);
11847         } else {
11848                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11849                 if (!is_ok (&error)) {
11850                         g_free (field);
11851                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11852                 }
11853         }
11854         if (fb->offset != -1)
11855                 field->offset = fb->offset;
11856         field->parent = klass;
11857         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11858
11859         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11860
11861         return field;
11862 }
11863 #endif
11864
11865 MonoType*
11866 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11867 {
11868         MonoError error;
11869         MonoClass *klass;
11870         MonoReflectionTypeBuilder *tb = NULL;
11871         gboolean is_dynamic = FALSE;
11872         MonoClass *geninst;
11873
11874         mono_loader_lock ();
11875
11876         if (is_sre_type_builder (mono_object_class (type))) {
11877                 tb = (MonoReflectionTypeBuilder *) type;
11878
11879                 is_dynamic = TRUE;
11880         } else if (is_sre_generic_instance (mono_object_class (type))) {
11881                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11882                 MonoReflectionType *gtd = rgi->generic_type;
11883
11884                 if (is_sre_type_builder (mono_object_class (gtd))) {
11885                         tb = (MonoReflectionTypeBuilder *)gtd;
11886                         is_dynamic = TRUE;
11887                 }
11888         }
11889
11890         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11891         if (tb && tb->generic_container)
11892                 mono_reflection_create_generic_class (tb);
11893
11894         MonoType *t = mono_reflection_type_get_handle (type, &error);
11895         mono_error_raise_exception (&error); /* FIXME don't raise here */
11896
11897         klass = mono_class_from_mono_type (t);
11898         if (!klass->generic_container) {
11899                 mono_loader_unlock ();
11900                 return NULL;
11901         }
11902
11903         if (klass->wastypebuilder) {
11904                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11905
11906                 is_dynamic = TRUE;
11907         }
11908
11909         mono_loader_unlock ();
11910
11911         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11912
11913         return &geninst->byval_arg;
11914 }
11915
11916 MonoClass*
11917 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11918 {
11919         MonoGenericClass *gclass;
11920         MonoGenericInst *inst;
11921
11922         g_assert (klass->generic_container);
11923
11924         inst = mono_metadata_get_generic_inst (type_argc, types);
11925         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11926
11927         return mono_generic_class_get_class (gclass);
11928 }
11929
11930 MonoReflectionMethod*
11931 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11932 {
11933         MonoError error;
11934         MonoClass *klass;
11935         MonoMethod *method, *inflated;
11936         MonoMethodInflated *imethod;
11937         MonoGenericContext tmp_context;
11938         MonoGenericInst *ginst;
11939         MonoType **type_argv;
11940         int count, i;
11941
11942         /*FIXME but this no longer should happen*/
11943         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11944 #ifndef DISABLE_REFLECTION_EMIT
11945                 MonoReflectionMethodBuilder *mb = NULL;
11946                 MonoType *tb;
11947                 MonoClass *klass;
11948
11949                 mb = (MonoReflectionMethodBuilder *) rmethod;
11950                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11951                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11952                 klass = mono_class_from_mono_type (tb);
11953
11954                 method = methodbuilder_to_mono_method (klass, mb, &error);
11955                 if (!method)
11956                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11957 #else
11958                 g_assert_not_reached ();
11959                 method = NULL;
11960 #endif
11961         } else {
11962                 method = rmethod->method;
11963         }
11964
11965         klass = method->klass;
11966
11967         if (method->is_inflated)
11968                 method = ((MonoMethodInflated *) method)->declaring;
11969
11970         count = mono_method_signature (method)->generic_param_count;
11971         if (count != mono_array_length (types))
11972                 return NULL;
11973
11974         type_argv = g_new0 (MonoType *, count);
11975         for (i = 0; i < count; i++) {
11976                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11977                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11978                 if (!is_ok (&error)) {
11979                         g_free (type_argv);
11980                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11981                 }
11982         }
11983         ginst = mono_metadata_get_generic_inst (count, type_argv);
11984         g_free (type_argv);
11985
11986         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11987         tmp_context.method_inst = ginst;
11988
11989         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11990         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11991         imethod = (MonoMethodInflated *) inflated;
11992
11993         /*FIXME but I think this is no longer necessary*/
11994         if (image_is_dynamic (method->klass->image)) {
11995                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11996                 /*
11997                  * This table maps metadata structures representing inflated methods/fields
11998                  * to the reflection objects representing their generic definitions.
11999                  */
12000                 mono_image_lock ((MonoImage*)image);
12001                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12002                 mono_image_unlock ((MonoImage*)image);
12003         }
12004
12005         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12006                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12007         
12008         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12009         mono_error_raise_exception (&error); /* FIXME don't raise here */
12010         return ret;
12011 }
12012
12013 #ifndef DISABLE_REFLECTION_EMIT
12014
12015 static MonoMethod *
12016 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12017 {
12018         MonoMethodInflated *imethod;
12019         MonoGenericContext *context;
12020         int i;
12021
12022         /*
12023          * With generic code sharing the klass might not be inflated.
12024          * This can happen because classes inflated with their own
12025          * type arguments are "normalized" to the uninflated class.
12026          */
12027         if (!klass->generic_class)
12028                 return method;
12029
12030         context = mono_class_get_context (klass);
12031
12032         if (klass->method.count && klass->methods) {
12033                 /* Find the already created inflated method */
12034                 for (i = 0; i < klass->method.count; ++i) {
12035                         g_assert (klass->methods [i]->is_inflated);
12036                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12037                                 break;
12038                 }
12039                 g_assert (i < klass->method.count);
12040                 imethod = (MonoMethodInflated*)klass->methods [i];
12041         } else {
12042                 MonoError error;
12043                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12044                 mono_error_assert_ok (&error);
12045         }
12046
12047         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12048                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12049
12050                 mono_image_lock ((MonoImage*)image);
12051                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12052                 mono_image_unlock ((MonoImage*)image);
12053         }
12054         return (MonoMethod *) imethod;
12055 }
12056
12057 static MonoMethod *
12058 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12059 {
12060         MonoMethod *method;
12061         MonoClass *gklass;
12062
12063         mono_error_init (error);
12064
12065         MonoClass *type_class = mono_object_class (type);
12066
12067         if (is_sre_generic_instance (type_class)) {
12068                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12069                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12070                 return_val_if_nok (error, NULL);
12071                 gklass = mono_class_from_mono_type (generic_type);
12072         } else if (is_sre_type_builder (type_class)) {
12073                 MonoType *t = mono_reflection_type_get_handle (type, error);
12074                 return_val_if_nok (error, NULL);
12075                 gklass = mono_class_from_mono_type (t);
12076         } else if (type->type) {
12077                 gklass = mono_class_from_mono_type (type->type);
12078                 gklass = mono_class_get_generic_type_definition (gklass);
12079         } else {
12080                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12081         }
12082
12083         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12084                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12085                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12086                 else {
12087                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12088                         if (!method)
12089                                 return NULL;
12090                 }
12091         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12092                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12093                 if (!method)
12094                         return NULL;
12095         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12096                 method = ((MonoReflectionMethod *) obj)->method;
12097         else {
12098                 method = NULL; /* prevent compiler warning */
12099                 g_error ("can't handle type %s", obj->vtable->klass->name);
12100         }
12101
12102         MonoType *t = mono_reflection_type_get_handle (type, error);
12103         return_val_if_nok (error, NULL);
12104         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12105 }
12106
12107 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12108 void
12109 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12110 {
12111         MonoError error;
12112         MonoGenericClass *gclass;
12113         MonoDynamicGenericClass *dgclass;
12114         MonoClass *klass, *gklass;
12115         MonoType *gtype;
12116         int i;
12117
12118         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12119         mono_error_raise_exception (&error); /* FIXME don't raise here */
12120         klass = mono_class_from_mono_type (gtype);
12121         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12122         gclass = gtype->data.generic_class;
12123
12124         if (!gclass->is_dynamic)
12125                 return;
12126
12127         dgclass = (MonoDynamicGenericClass *) gclass;
12128
12129         if (dgclass->initialized)
12130                 return;
12131
12132         gklass = gclass->container_class;
12133         mono_class_init (gklass);
12134
12135         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12136
12137         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12138         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12139         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12140
12141         for (i = 0; i < dgclass->count_fields; i++) {
12142                 MonoError error;
12143                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12144                 MonoClassField *field, *inflated_field = NULL;
12145
12146                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12147                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12148                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12149                         field = ((MonoReflectionField *) obj)->field;
12150                 else {
12151                         field = NULL; /* prevent compiler warning */
12152                         g_assert_not_reached ();
12153                 }
12154
12155                 dgclass->fields [i] = *field;
12156                 dgclass->fields [i].parent = klass;
12157                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12158                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12159                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12160                 dgclass->field_generic_types [i] = field->type;
12161                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12162                 dgclass->field_objects [i] = obj;
12163
12164                 if (inflated_field) {
12165                         g_free (inflated_field);
12166                 } else {
12167                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12168                 }
12169         }
12170
12171         dgclass->initialized = TRUE;
12172 }
12173
12174 void
12175 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12176 {
12177         MonoDynamicGenericClass *dgclass;
12178         int i;
12179
12180         g_assert (gclass->is_dynamic);
12181
12182         dgclass = (MonoDynamicGenericClass *)gclass;
12183
12184         for (i = 0; i < dgclass->count_fields; ++i) {
12185                 MonoClassField *field = dgclass->fields + i;
12186                 mono_metadata_free_type (field->type);
12187                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12188         }
12189 }
12190
12191 static void
12192 fix_partial_generic_class (MonoClass *klass)
12193 {
12194         MonoClass *gklass = klass->generic_class->container_class;
12195         MonoDynamicGenericClass *dgclass;
12196         int i;
12197
12198         if (klass->wastypebuilder)
12199                 return;
12200
12201         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12202         if (klass->parent != gklass->parent) {
12203                 MonoError error;
12204                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12205                 if (mono_error_ok (&error)) {
12206                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12207                         mono_metadata_free_type (parent_type);
12208                         if (parent != klass->parent) {
12209                                 /*fool mono_class_setup_parent*/
12210                                 klass->supertypes = NULL;
12211                                 mono_class_setup_parent (klass, parent);
12212                         }
12213                 } else {
12214                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12215                         mono_error_cleanup (&error);
12216                         if (gklass->wastypebuilder)
12217                                 klass->wastypebuilder = TRUE;
12218                         return;
12219                 }
12220         }
12221
12222         if (!dgclass->initialized)
12223                 return;
12224
12225         if (klass->method.count != gklass->method.count) {
12226                 klass->method.count = gklass->method.count;
12227                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12228
12229                 for (i = 0; i < klass->method.count; i++) {
12230                         MonoError error;
12231                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12232                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12233                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12234                 }
12235         }
12236
12237         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12238                 klass->interface_count = gklass->interface_count;
12239                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12240                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12241
12242                 for (i = 0; i < gklass->interface_count; ++i) {
12243                         MonoError error;
12244                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12245                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12246
12247                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12248                         mono_metadata_free_type (iface_type);
12249
12250                         ensure_runtime_vtable (klass->interfaces [i], &error);
12251                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12252                 }
12253                 klass->interfaces_inited = 1;
12254         }
12255
12256         if (klass->field.count != gklass->field.count) {
12257                 klass->field.count = gklass->field.count;
12258                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12259
12260                 for (i = 0; i < klass->field.count; i++) {
12261                         MonoError error;
12262                         klass->fields [i] = gklass->fields [i];
12263                         klass->fields [i].parent = klass;
12264                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12265                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12266                 }
12267         }
12268
12269         /*We can only finish with this klass once it's parent has as well*/
12270         if (gklass->wastypebuilder)
12271                 klass->wastypebuilder = TRUE;
12272         return;
12273 }
12274
12275 /**
12276  * ensure_generic_class_runtime_vtable:
12277  * @klass a generic class
12278  * @error set on error
12279  *
12280  * Ensures that the generic container of @klass has a vtable and
12281  * returns TRUE on success.  On error returns FALSE and sets @error.
12282  */
12283 static gboolean
12284 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12285 {
12286         MonoClass *gklass = klass->generic_class->container_class;
12287
12288         mono_error_init (error);
12289
12290         if (!ensure_runtime_vtable (gklass, error))
12291                 return FALSE;
12292
12293         fix_partial_generic_class (klass);
12294
12295         return TRUE;
12296 }
12297
12298 /**
12299  * ensure_runtime_vtable:
12300  * @klass the class
12301  * @error set on error
12302  *
12303  * Ensures that @klass has a vtable and returns TRUE on success. On
12304  * error returns FALSE and sets @error.
12305  */
12306 static gboolean
12307 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12308 {
12309         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12310         int i, num, j;
12311
12312         mono_error_init (error);
12313
12314         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12315                 return TRUE;
12316         if (klass->parent)
12317                 if (!ensure_runtime_vtable (klass->parent, error))
12318                         return FALSE;
12319
12320         if (tb) {
12321                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12322                 num += tb->num_methods;
12323                 klass->method.count = num;
12324                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12325                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12326                 for (i = 0; i < num; ++i) {
12327                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12328                         if (!ctor)
12329                                 return FALSE;
12330                         klass->methods [i] = ctor;
12331                 }
12332                 num = tb->num_methods;
12333                 j = i;
12334                 for (i = 0; i < num; ++i) {
12335                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12336                         if (!meth)
12337                                 return FALSE;
12338                         klass->methods [j++] = meth;
12339                 }
12340         
12341                 if (tb->interfaces) {
12342                         klass->interface_count = mono_array_length (tb->interfaces);
12343                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12344                         for (i = 0; i < klass->interface_count; ++i) {
12345                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12346                                 return_val_if_nok (error, FALSE);
12347                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12348                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12349                                         return FALSE;
12350                         }
12351                         klass->interfaces_inited = 1;
12352                 }
12353         } else if (klass->generic_class){
12354                 if (!ensure_generic_class_runtime_vtable (klass, error))
12355                         return FALSE;
12356         }
12357
12358         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12359                 int slot_num = 0;
12360                 for (i = 0; i < klass->method.count; ++i) {
12361                         MonoMethod *im = klass->methods [i];
12362                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12363                                 im->slot = slot_num++;
12364                 }
12365                 
12366                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12367                 mono_class_setup_interface_offsets (klass);
12368                 mono_class_setup_interface_id (klass);
12369         }
12370
12371         /*
12372          * The generic vtable is needed even if image->run is not set since some
12373          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12374          * method->slot being defined.
12375          */
12376
12377         /* 
12378          * tb->methods could not be freed since it is used for determining 
12379          * overrides during dynamic vtable construction.
12380          */
12381
12382         return TRUE;
12383 }
12384
12385 static MonoMethod*
12386 mono_reflection_method_get_handle (MonoObject *method)
12387 {
12388         MonoError error;
12389         MonoClass *klass = mono_object_class (method);
12390         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12391                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12392                 return sr_method->method;
12393         }
12394         if (is_sre_method_builder (klass)) {
12395                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12396                 return mb->mhandle;
12397         }
12398         if (is_sre_method_on_tb_inst (klass)) {
12399                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12400                 MonoMethod *result;
12401                 /*FIXME move this to a proper method and unify with resolve_object*/
12402                 if (m->method_args) {
12403                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12404                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12405                 } else {
12406                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12407                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12408                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12409                         MonoMethod *mono_method;
12410
12411                         if (is_sre_method_builder (mono_object_class (m->mb)))
12412                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12413                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12414                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12415                         else
12416                                 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)));
12417
12418                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12419                 }
12420                 return result;
12421         }
12422
12423         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12424         return NULL;
12425 }
12426
12427 void
12428 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12429 {
12430         MonoReflectionTypeBuilder *tb;
12431         int i, j, onum;
12432         MonoReflectionMethod *m;
12433
12434         *overrides = NULL;
12435         *num_overrides = 0;
12436
12437         g_assert (image_is_dynamic (klass->image));
12438
12439         if (!mono_class_get_ref_info (klass))
12440                 return;
12441
12442         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12443
12444         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12445
12446         onum = 0;
12447         if (tb->methods) {
12448                 for (i = 0; i < tb->num_methods; ++i) {
12449                         MonoReflectionMethodBuilder *mb = 
12450                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12451                         if (mb->override_methods)
12452                                 onum += mono_array_length (mb->override_methods);
12453                 }
12454         }
12455
12456         if (onum) {
12457                 *overrides = g_new0 (MonoMethod*, onum * 2);
12458
12459                 onum = 0;
12460                 for (i = 0; i < tb->num_methods; ++i) {
12461                         MonoReflectionMethodBuilder *mb = 
12462                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12463                         if (mb->override_methods) {
12464                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12465                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12466
12467                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12468                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12469
12470                                         g_assert (mb->mhandle);
12471
12472                                         onum ++;
12473                                 }
12474                         }
12475                 }
12476         }
12477
12478         *num_overrides = onum;
12479 }
12480
12481 static void
12482 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12483 {
12484         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12485         MonoReflectionFieldBuilder *fb;
12486         MonoClassField *field;
12487         MonoImage *image = klass->image;
12488         const char *p, *p2;
12489         int i;
12490         guint32 len, idx, real_size = 0;
12491
12492         klass->field.count = tb->num_fields;
12493         klass->field.first = 0;
12494
12495         mono_error_init (error);
12496
12497         if (tb->class_size) {
12498                 if ((tb->packing_size & 0xffffff00) != 0) {
12499                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12500                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12501                         return;
12502                 }
12503                 klass->packing_size = tb->packing_size;
12504                 real_size = klass->instance_size + tb->class_size;
12505         }
12506
12507         if (!klass->field.count) {
12508                 klass->instance_size = MAX (klass->instance_size, real_size);
12509                 return;
12510         }
12511         
12512         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12513         mono_class_alloc_ext (klass);
12514         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12515         /*
12516         This is, guess what, a hack.
12517         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12518         On the static path no field class is resolved, only types are built. This is the right thing to do
12519         but we suck.
12520         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12521         */
12522         klass->size_inited = 1;
12523
12524         for (i = 0; i < klass->field.count; ++i) {
12525                 MonoArray *rva_data;
12526                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12527                 field = &klass->fields [i];
12528                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12529                 if (!mono_error_ok (error))
12530                         return;
12531                 if (fb->attrs) {
12532                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12533                         return_if_nok (error);
12534                         field->type = mono_metadata_type_dup (klass->image, type);
12535                         field->type->attrs = fb->attrs;
12536                 } else {
12537                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12538                         return_if_nok (error);
12539                 }
12540
12541                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12542                         char *base = mono_array_addr (rva_data, char, 0);
12543                         size_t size = mono_array_length (rva_data);
12544                         char *data = (char *)mono_image_alloc (klass->image, size);
12545                         memcpy (data, base, size);
12546                         klass->ext->field_def_values [i].data = data;
12547                 }
12548                 if (fb->offset != -1)
12549                         field->offset = fb->offset;
12550                 field->parent = klass;
12551                 fb->handle = field;
12552                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12553
12554                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12555                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12556                 }
12557                 if (fb->def_value) {
12558                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12559                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12560                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12561                         /* Copy the data from the blob since it might get realloc-ed */
12562                         p = assembly->blob.data + idx;
12563                         len = mono_metadata_decode_blob_size (p, &p2);
12564                         len += p2 - p;
12565                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12566                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12567                 }
12568         }
12569
12570         klass->instance_size = MAX (klass->instance_size, real_size);
12571         mono_class_layout_fields (klass);
12572 }
12573
12574 static void
12575 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12576 {
12577         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12578         MonoReflectionPropertyBuilder *pb;
12579         MonoImage *image = klass->image;
12580         MonoProperty *properties;
12581         int i;
12582
12583         mono_error_init (error);
12584
12585         if (!klass->ext)
12586                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12587
12588         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12589         klass->ext->property.first = 0;
12590
12591         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12592         klass->ext->properties = properties;
12593         for (i = 0; i < klass->ext->property.count; ++i) {
12594                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12595                 properties [i].parent = klass;
12596                 properties [i].attrs = pb->attrs;
12597                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12598                 if (!mono_error_ok (error))
12599                         return;
12600                 if (pb->get_method)
12601                         properties [i].get = pb->get_method->mhandle;
12602                 if (pb->set_method)
12603                         properties [i].set = pb->set_method->mhandle;
12604
12605                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12606                 if (pb->def_value) {
12607                         guint32 len, idx;
12608                         const char *p, *p2;
12609                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12610                         if (!klass->ext->prop_def_values)
12611                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12612                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12613                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12614                         /* Copy the data from the blob since it might get realloc-ed */
12615                         p = assembly->blob.data + idx;
12616                         len = mono_metadata_decode_blob_size (p, &p2);
12617                         len += p2 - p;
12618                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12619                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12620                 }
12621         }
12622 }
12623
12624 MonoReflectionEvent *
12625 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12626 {
12627         MonoError error;
12628         MonoEvent *event = g_new0 (MonoEvent, 1);
12629         MonoClass *klass;
12630
12631         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12632         mono_error_raise_exception (&error); /* FIXME don't raise here */
12633         klass = mono_class_from_mono_type (type);
12634
12635         event->parent = klass;
12636         event->attrs = eb->attrs;
12637         event->name = mono_string_to_utf8 (eb->name);
12638         if (eb->add_method)
12639                 event->add = eb->add_method->mhandle;
12640         if (eb->remove_method)
12641                 event->remove = eb->remove_method->mhandle;
12642         if (eb->raise_method)
12643                 event->raise = eb->raise_method->mhandle;
12644
12645 #ifndef MONO_SMALL_CONFIG
12646         if (eb->other_methods) {
12647                 int j;
12648                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12649                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12650                         MonoReflectionMethodBuilder *mb = 
12651                                 mono_array_get (eb->other_methods,
12652                                                 MonoReflectionMethodBuilder*, j);
12653                         event->other [j] = mb->mhandle;
12654                 }
12655         }
12656 #endif
12657
12658         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12659         mono_error_raise_exception (&error); /* FIXME don't raise here */
12660         return ev_obj;
12661 }
12662
12663 static void
12664 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12665 {
12666         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12667         MonoReflectionEventBuilder *eb;
12668         MonoImage *image = klass->image;
12669         MonoEvent *events;
12670         int i;
12671
12672         mono_error_init (error);
12673
12674         if (!klass->ext)
12675                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12676
12677         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12678         klass->ext->event.first = 0;
12679
12680         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12681         klass->ext->events = events;
12682         for (i = 0; i < klass->ext->event.count; ++i) {
12683                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12684                 events [i].parent = klass;
12685                 events [i].attrs = eb->attrs;
12686                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12687                 if (!mono_error_ok (error))
12688                         return;
12689                 if (eb->add_method)
12690                         events [i].add = eb->add_method->mhandle;
12691                 if (eb->remove_method)
12692                         events [i].remove = eb->remove_method->mhandle;
12693                 if (eb->raise_method)
12694                         events [i].raise = eb->raise_method->mhandle;
12695
12696 #ifndef MONO_SMALL_CONFIG
12697                 if (eb->other_methods) {
12698                         int j;
12699                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12700                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12701                                 MonoReflectionMethodBuilder *mb = 
12702                                         mono_array_get (eb->other_methods,
12703                                                                         MonoReflectionMethodBuilder*, j);
12704                                 events [i].other [j] = mb->mhandle;
12705                         }
12706                 }
12707 #endif
12708                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12709         }
12710 }
12711
12712 static gboolean
12713 remove_instantiations_of_and_ensure_contents (gpointer key,
12714                                                   gpointer value,
12715                                                   gpointer user_data)
12716 {
12717         MonoType *type = (MonoType*)key;
12718         MonoClass *klass = (MonoClass*)user_data;
12719
12720         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12721                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12722                 return TRUE;
12723         } else
12724                 return FALSE;
12725 }
12726
12727 static void
12728 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12729 {
12730         mono_error_init (error);
12731         int i;
12732
12733         if (!arr)
12734                 return;
12735
12736         for (i = 0; i < mono_array_length (arr); ++i) {
12737                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12738                 if (!mono_error_ok (error))
12739                         break;
12740         }
12741 }
12742
12743 MonoReflectionType*
12744 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12745 {
12746         MonoError error;
12747         MonoClass *klass;
12748         MonoDomain* domain;
12749         MonoReflectionType* res;
12750         int i, j;
12751
12752         domain = mono_object_domain (tb);
12753         klass = mono_class_from_mono_type (tb->type.type);
12754
12755         /*
12756          * Check for user defined Type subclasses.
12757          */
12758         RESOLVE_TYPE (tb->parent, &error);
12759         mono_error_raise_exception (&error); /* FIXME don't raise here */
12760         check_array_for_usertypes (tb->interfaces, &error);
12761         mono_error_raise_exception (&error); /*FIXME don't raise here */
12762         if (tb->fields) {
12763                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12764                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12765                         if (fb) {
12766                                 RESOLVE_TYPE (fb->type, &error);
12767                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12768                                 check_array_for_usertypes (fb->modreq, &error);
12769                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12770                                 check_array_for_usertypes (fb->modopt, &error);
12771                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12772                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12773                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12774                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12775                                 }
12776                         }
12777                 }
12778         }
12779         if (tb->methods) {
12780                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12781                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12782                         if (mb) {
12783                                 RESOLVE_TYPE (mb->rtype, &error);
12784                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12785                                 check_array_for_usertypes (mb->return_modreq, &error);
12786                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12787                                 check_array_for_usertypes (mb->return_modopt, &error);
12788                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12789                                 check_array_for_usertypes (mb->parameters, &error);
12790                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12791                                 if (mb->param_modreq)
12792                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12793                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12794                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12795                                         }
12796                                 if (mb->param_modopt)
12797                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12798                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12799                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12800                                         }
12801                         }
12802                 }
12803         }
12804         if (tb->ctors) {
12805                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12806                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12807                         if (mb) {
12808                                 check_array_for_usertypes (mb->parameters, &error);
12809                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12810                                 if (mb->param_modreq)
12811                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12812                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12813                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12814                                         }
12815                                 if (mb->param_modopt)
12816                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12817                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12818                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12819                                         }
12820                         }
12821                 }
12822         }
12823
12824         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12825
12826         /* 
12827          * we need to lock the domain because the lock will be taken inside
12828          * So, we need to keep the locking order correct.
12829          */
12830         mono_loader_lock ();
12831         mono_domain_lock (domain);
12832         if (klass->wastypebuilder) {
12833                 mono_domain_unlock (domain);
12834                 mono_loader_unlock ();
12835
12836                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12837                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12838
12839                 return res;
12840         }
12841         /*
12842          * Fields to set in klass:
12843          * the various flags: delegate/unicode/contextbound etc.
12844          */
12845         klass->flags = tb->attrs;
12846         klass->has_cctor = 1;
12847         klass->has_finalize = 1;
12848         klass->has_finalize_inited = 1;
12849
12850         mono_class_setup_parent (klass, klass->parent);
12851         /* fool mono_class_setup_supertypes */
12852         klass->supertypes = NULL;
12853         mono_class_setup_supertypes (klass);
12854         mono_class_setup_mono_type (klass);
12855
12856 #if 0
12857         if (!((MonoDynamicImage*)klass->image)->run) {
12858                 if (klass->generic_container) {
12859                         /* FIXME: The code below can't handle generic classes */
12860                         klass->wastypebuilder = TRUE;
12861                         mono_loader_unlock ();
12862                         mono_domain_unlock (domain);
12863
12864                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12865                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12866
12867                         return res;
12868                 }
12869         }
12870 #endif
12871
12872         /* enums are done right away */
12873         if (!klass->enumtype)
12874                 if (!ensure_runtime_vtable (klass, &error))
12875                         goto failure;
12876
12877         if (tb->subtypes) {
12878                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12879                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12880                         mono_class_alloc_ext (klass);
12881                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12882                         if (!is_ok (&error)) goto failure;
12883                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12884                 }
12885         }
12886
12887         klass->nested_classes_inited = TRUE;
12888
12889         /* fields and object layout */
12890         if (klass->parent) {
12891                 if (!klass->parent->size_inited)
12892                         mono_class_init (klass->parent);
12893                 klass->instance_size = klass->parent->instance_size;
12894                 klass->sizes.class_size = 0;
12895                 klass->min_align = klass->parent->min_align;
12896                 /* if the type has no fields we won't call the field_setup
12897                  * routine which sets up klass->has_references.
12898                  */
12899                 klass->has_references |= klass->parent->has_references;
12900         } else {
12901                 klass->instance_size = sizeof (MonoObject);
12902                 klass->min_align = 1;
12903         }
12904
12905         /* FIXME: handle packing_size and instance_size */
12906         typebuilder_setup_fields (klass, &error);
12907         if (!mono_error_ok (&error))
12908                 goto failure;
12909         typebuilder_setup_properties (klass, &error);
12910         if (!mono_error_ok (&error))
12911                 goto failure;
12912
12913         typebuilder_setup_events (klass, &error);
12914         if (!mono_error_ok (&error))
12915                 goto failure;
12916
12917         klass->wastypebuilder = TRUE;
12918
12919         /* 
12920          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12921          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12922          * we want to return normal System.MonoType objects, so clear these out from the cache.
12923          *
12924          * Together with this we must ensure the contents of all instances to match the created type.
12925          */
12926         if (domain->type_hash && klass->generic_container)
12927                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12928
12929         mono_domain_unlock (domain);
12930         mono_loader_unlock ();
12931
12932         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12933                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12934                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12935         }
12936
12937         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12938         mono_error_raise_exception (&error); /* FIXME don't raise here */
12939
12940         g_assert (res != (MonoReflectionType*)tb);
12941
12942         return res;
12943
12944 failure:
12945         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12946         klass->wastypebuilder = TRUE;
12947         mono_domain_unlock (domain);
12948         mono_loader_unlock ();
12949         mono_error_raise_exception (&error);
12950         return NULL;
12951 }
12952
12953 void
12954 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12955 {
12956         MonoGenericParamFull *param;
12957         MonoImage *image;
12958         MonoClass *pklass;
12959         MonoError error;
12960
12961         image = &gparam->tbuilder->module->dynamic_image->image;
12962
12963         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12964
12965         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12966         g_assert (mono_error_ok (&error));
12967         param->param.num = gparam->index;
12968
12969         if (gparam->mbuilder) {
12970                 if (!gparam->mbuilder->generic_container) {
12971                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12972                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12973
12974                         MonoClass *klass = mono_class_from_mono_type (tb);
12975                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12976                         gparam->mbuilder->generic_container->is_method = TRUE;
12977                         /* 
12978                          * Cannot set owner.method, since the MonoMethod is not created yet.
12979                          * Set the image field instead, so type_in_image () works.
12980                          */
12981                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12982                         gparam->mbuilder->generic_container->owner.image = klass->image;
12983                 }
12984                 param->param.owner = gparam->mbuilder->generic_container;
12985         } else if (gparam->tbuilder) {
12986                 if (!gparam->tbuilder->generic_container) {
12987                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12988                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12989                         MonoClass *klass = mono_class_from_mono_type (tb);
12990                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12991                         gparam->tbuilder->generic_container->owner.klass = klass;
12992                 }
12993                 param->param.owner = gparam->tbuilder->generic_container;
12994         }
12995
12996         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12997
12998         gparam->type.type = &pklass->byval_arg;
12999
13000         mono_class_set_ref_info (pklass, gparam);
13001         mono_image_append_class_to_reflection_info_set (pklass);
13002 }
13003
13004 MonoArray *
13005 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13006 {
13007         MonoError error;
13008         MonoReflectionModuleBuilder *module = sig->module;
13009         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13010         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13011         guint32 buflen, i;
13012         MonoArray *result;
13013         SigBuffer buf;
13014
13015         check_array_for_usertypes (sig->arguments, &error);
13016         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13017
13018         sigbuffer_init (&buf, 32);
13019
13020         sigbuffer_add_value (&buf, 0x07);
13021         sigbuffer_add_value (&buf, na);
13022         if (assembly != NULL){
13023                 for (i = 0; i < na; ++i) {
13024                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13025                         encode_reflection_type (assembly, type, &buf, &error);
13026                         if (!is_ok (&error)) goto fail;
13027                 }
13028         }
13029
13030         buflen = buf.p - buf.buf;
13031         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13032         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13033         sigbuffer_free (&buf);
13034         return result;
13035 fail:
13036         sigbuffer_free (&buf);
13037         mono_error_raise_exception (&error); /* FIXME don't raise here */
13038         return NULL;
13039 }
13040
13041 MonoArray *
13042 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13043 {
13044         MonoError error;
13045         MonoDynamicImage *assembly = sig->module->dynamic_image;
13046         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13047         guint32 buflen, i;
13048         MonoArray *result;
13049         SigBuffer buf;
13050
13051         check_array_for_usertypes (sig->arguments, &error);
13052         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13053
13054         sigbuffer_init (&buf, 32);
13055
13056         sigbuffer_add_value (&buf, 0x06);
13057         for (i = 0; i < na; ++i) {
13058                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13059                 encode_reflection_type (assembly, type, &buf, &error);
13060                 if (!is_ok (&error))
13061                         goto fail;
13062         }
13063
13064         buflen = buf.p - buf.buf;
13065         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13066         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13067         sigbuffer_free (&buf);
13068
13069         return result;
13070 fail:
13071         sigbuffer_free (&buf);
13072         mono_error_raise_exception (&error); /* FIXME don't raise here */
13073         return NULL;
13074 }
13075
13076 typedef struct {
13077         MonoMethod *handle;
13078         MonoDomain *domain;
13079 } DynamicMethodReleaseData;
13080
13081 /*
13082  * The runtime automatically clean up those after finalization.
13083 */      
13084 static MonoReferenceQueue *dynamic_method_queue;
13085
13086 static void
13087 free_dynamic_method (void *dynamic_method)
13088 {
13089         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13090         MonoDomain *domain = data->domain;
13091         MonoMethod *method = data->handle;
13092         guint32 dis_link;
13093
13094         mono_domain_lock (domain);
13095         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13096         g_hash_table_remove (domain->method_to_dyn_method, method);
13097         mono_domain_unlock (domain);
13098         g_assert (dis_link);
13099         mono_gchandle_free (dis_link);
13100
13101         mono_runtime_free_method (domain, method);
13102         g_free (data);
13103 }
13104
13105 void 
13106 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13107 {
13108         MonoError error;
13109         MonoReferenceQueue *queue;
13110         MonoMethod *handle;
13111         DynamicMethodReleaseData *release_data;
13112         ReflectionMethodBuilder rmb;
13113         MonoMethodSignature *sig;
13114         MonoClass *klass;
13115         MonoDomain *domain;
13116         GSList *l;
13117         int i;
13118
13119         if (mono_runtime_is_shutting_down ())
13120                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13121
13122         if (!(queue = dynamic_method_queue)) {
13123                 mono_loader_lock ();
13124                 if (!(queue = dynamic_method_queue))
13125                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13126                 mono_loader_unlock ();
13127         }
13128
13129         sig = dynamic_method_to_signature (mb);
13130
13131         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13132
13133         /*
13134          * Resolve references.
13135          */
13136         /* 
13137          * Every second entry in the refs array is reserved for storing handle_class,
13138          * which is needed by the ldtoken implementation in the JIT.
13139          */
13140         rmb.nrefs = mb->nrefs;
13141         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13142         for (i = 0; i < mb->nrefs; i += 2) {
13143                 MonoClass *handle_class;
13144                 gpointer ref;
13145                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13146
13147                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13148                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13149                         /*
13150                          * The referenced DynamicMethod should already be created by the managed
13151                          * code, except in the case of circular references. In that case, we store
13152                          * method in the refs array, and fix it up later when the referenced 
13153                          * DynamicMethod is created.
13154                          */
13155                         if (method->mhandle) {
13156                                 ref = method->mhandle;
13157                         } else {
13158                                 /* FIXME: GC object stored in unmanaged memory */
13159                                 ref = method;
13160
13161                                 /* FIXME: GC object stored in unmanaged memory */
13162                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13163                         }
13164                         handle_class = mono_defaults.methodhandle_class;
13165                 } else {
13166                         MonoException *ex = NULL;
13167                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13168                         if (!ref)
13169                                 ex = mono_get_exception_type_load (NULL, NULL);
13170                         else if (mono_security_core_clr_enabled ())
13171                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13172
13173                         if (ex) {
13174                                 g_free (rmb.refs);
13175                                 mono_raise_exception (ex);
13176                                 return;
13177                         }
13178                 }
13179
13180                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13181                 rmb.refs [i + 1] = handle_class;
13182         }               
13183
13184         if (mb->owner) {
13185                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13186                 if (!is_ok (&error)) {
13187                         g_free (rmb.refs);
13188                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13189                 }
13190                 klass = mono_class_from_mono_type (owner_type);
13191         } else {
13192                 klass = mono_defaults.object_class;
13193         }
13194
13195         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13196         release_data = g_new (DynamicMethodReleaseData, 1);
13197         release_data->handle = handle;
13198         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13199         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13200                 g_free (release_data);
13201
13202         /* Fix up refs entries pointing at us */
13203         for (l = mb->referenced_by; l; l = l->next) {
13204                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13205                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13206                 gpointer *data;
13207                 
13208                 g_assert (method->mhandle);
13209
13210                 data = (gpointer*)wrapper->method_data;
13211                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13212                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13213                                 data [i + 1] = mb->mhandle;
13214                 }
13215         }
13216         g_slist_free (mb->referenced_by);
13217
13218         g_free (rmb.refs);
13219
13220         /* ilgen is no longer needed */
13221         mb->ilgen = NULL;
13222
13223         domain = mono_domain_get ();
13224         mono_domain_lock (domain);
13225         if (!domain->method_to_dyn_method)
13226                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13227         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13228         mono_domain_unlock (domain);
13229 }
13230
13231 #endif /* DISABLE_REFLECTION_EMIT */
13232
13233 /**
13234  * 
13235  * mono_reflection_is_valid_dynamic_token:
13236  * 
13237  * Returns TRUE if token is valid.
13238  * 
13239  */
13240 gboolean
13241 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13242 {
13243         return lookup_dyn_token (image, token) != NULL;
13244 }
13245
13246 MonoMethodSignature *
13247 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13248 {
13249         MonoMethodSignature *sig;
13250         g_assert (image_is_dynamic (image));
13251
13252         mono_error_init (error);
13253
13254         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13255         if (sig)
13256                 return sig;
13257
13258         return mono_method_signature_checked (method, error);
13259 }
13260
13261 #ifndef DISABLE_REFLECTION_EMIT
13262
13263 /**
13264  * mono_reflection_lookup_dynamic_token:
13265  *
13266  * Finish the Builder object pointed to by TOKEN and return the corresponding
13267  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13268  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13269  * mapping table.
13270  *
13271  * LOCKING: Take the loader lock
13272  */
13273 gpointer
13274 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13275 {
13276         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13277         MonoObject *obj;
13278         MonoClass *klass;
13279
13280         obj = lookup_dyn_token (assembly, token);
13281         if (!obj) {
13282                 if (valid_token)
13283                         g_error ("Could not find required dynamic token 0x%08x", token);
13284                 else
13285                         return NULL;
13286         }
13287
13288         if (!handle_class)
13289                 handle_class = &klass;
13290         return resolve_object (image, obj, handle_class, context);
13291 }
13292
13293 /*
13294  * ensure_complete_type:
13295  *
13296  *   Ensure that KLASS is completed if it is a dynamic type, or references
13297  * dynamic types.
13298  */
13299 static void
13300 ensure_complete_type (MonoClass *klass)
13301 {
13302         MonoError error;
13303
13304         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13305                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13306
13307                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13308                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13309
13310                 // Asserting here could break a lot of code
13311                 //g_assert (klass->wastypebuilder);
13312         }
13313
13314         if (klass->generic_class) {
13315                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13316                 int i;
13317
13318                 for (i = 0; i < inst->type_argc; ++i) {
13319                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13320                 }
13321         }
13322 }
13323
13324 static gpointer
13325 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13326 {
13327         MonoError error;
13328         gpointer result = NULL;
13329
13330         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13331                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13332                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13333                 *handle_class = mono_defaults.string_class;
13334                 g_assert (result);
13335         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13336                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13337                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13338                 MonoClass *mc = mono_class_from_mono_type (type);
13339                 if (!mono_class_init (mc))
13340                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13341
13342                 if (context) {
13343                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13344                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13345
13346                         result = mono_class_from_mono_type (inflated);
13347                         mono_metadata_free_type (inflated);
13348                 } else {
13349                         result = mono_class_from_mono_type (type);
13350                 }
13351                 *handle_class = mono_defaults.typehandle_class;
13352                 g_assert (result);
13353         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13354                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13355                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13356                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13357                 result = ((MonoReflectionMethod*)obj)->method;
13358                 if (context) {
13359                         MonoError error;
13360                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13361                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13362                 }
13363                 *handle_class = mono_defaults.methodhandle_class;
13364                 g_assert (result);
13365         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13366                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13367                 result = mb->mhandle;
13368                 if (!result) {
13369                         /* Type is not yet created */
13370                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13371
13372                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13373                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13374
13375                         /*
13376                          * Hopefully this has been filled in by calling CreateType() on the
13377                          * TypeBuilder.
13378                          */
13379                         /*
13380                          * TODO: This won't work if the application finishes another 
13381                          * TypeBuilder instance instead of this one.
13382                          */
13383                         result = mb->mhandle;
13384                 }
13385                 if (context) {
13386                         MonoError error;
13387                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13388                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13389                 }
13390                 *handle_class = mono_defaults.methodhandle_class;
13391         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13392                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13393
13394                 result = cb->mhandle;
13395                 if (!result) {
13396                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13397
13398                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13399                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13400                         result = cb->mhandle;
13401                 }
13402                 if (context) {
13403                         MonoError error;
13404                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13405                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13406                 }
13407                 *handle_class = mono_defaults.methodhandle_class;
13408         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13409                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13410
13411                 ensure_complete_type (field->parent);
13412                 if (context) {
13413                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13414                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13415
13416                         MonoClass *klass = mono_class_from_mono_type (inflated);
13417                         MonoClassField *inflated_field;
13418                         gpointer iter = NULL;
13419                         mono_metadata_free_type (inflated);
13420                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13421                                 if (!strcmp (field->name, inflated_field->name))
13422                                         break;
13423                         }
13424                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13425                         result = inflated_field;
13426                 } else {
13427                         result = field;
13428                 }
13429                 *handle_class = mono_defaults.fieldhandle_class;
13430                 g_assert (result);
13431         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13432                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13433                 result = fb->handle;
13434
13435                 if (!result) {
13436                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13437
13438                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13439                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13440                         result = fb->handle;
13441                 }
13442
13443                 if (fb->handle && fb->handle->parent->generic_container) {
13444                         MonoClass *klass = fb->handle->parent;
13445                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13446                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13447
13448                         MonoClass *inflated = mono_class_from_mono_type (type);
13449
13450                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13451                         g_assert (result);
13452                         mono_metadata_free_type (type);
13453                 }
13454                 *handle_class = mono_defaults.fieldhandle_class;
13455         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13456                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13457                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13458                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13459                 MonoClass *klass;
13460
13461                 klass = type->data.klass;
13462                 if (klass->wastypebuilder) {
13463                         /* Already created */
13464                         result = klass;
13465                 }
13466                 else {
13467                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13468                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13469                         result = type->data.klass;
13470                         g_assert (result);
13471                 }
13472                 *handle_class = mono_defaults.typehandle_class;
13473         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13474                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13475                 MonoMethodSignature *sig;
13476                 int nargs, i;
13477
13478                 if (helper->arguments)
13479                         nargs = mono_array_length (helper->arguments);
13480                 else
13481                         nargs = 0;
13482
13483                 sig = mono_metadata_signature_alloc (image, nargs);
13484                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13485                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13486
13487                 if (helper->unmanaged_call_conv) { /* unmanaged */
13488                         sig->call_convention = helper->unmanaged_call_conv - 1;
13489                         sig->pinvoke = TRUE;
13490                 } else if (helper->call_conv & 0x02) {
13491                         sig->call_convention = MONO_CALL_VARARG;
13492                 } else {
13493                         sig->call_convention = MONO_CALL_DEFAULT;
13494                 }
13495
13496                 sig->param_count = nargs;
13497                 /* TODO: Copy type ? */
13498                 sig->ret = helper->return_type->type;
13499                 for (i = 0; i < nargs; ++i) {
13500                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13501                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13502                 }
13503
13504                 result = sig;
13505                 *handle_class = NULL;
13506         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13507                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13508                 /* Already created by the managed code */
13509                 g_assert (method->mhandle);
13510                 result = method->mhandle;
13511                 *handle_class = mono_defaults.methodhandle_class;
13512         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13513                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13514                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13515                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13516                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13517
13518                 result = mono_class_from_mono_type (type);
13519                 *handle_class = mono_defaults.typehandle_class;
13520                 g_assert (result);
13521                 mono_metadata_free_type (type);
13522         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13523                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13524                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13525                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13526                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13527
13528                 result = mono_class_from_mono_type (type);
13529                 *handle_class = mono_defaults.typehandle_class;
13530                 g_assert (result);
13531                 mono_metadata_free_type (type);
13532         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13533                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13534                 MonoClass *inflated;
13535                 MonoType *type;
13536                 MonoClassField *field;
13537
13538                 if (is_sre_field_builder (mono_object_class (f->fb)))
13539                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13540                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13541                         field = ((MonoReflectionField*)f->fb)->field;
13542                 else
13543                         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)));
13544
13545                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13546                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13547                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13548                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13549
13550                 inflated = mono_class_from_mono_type (type);
13551
13552                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13553                 ensure_complete_type (field->parent);
13554                 g_assert (result);
13555                 mono_metadata_free_type (type);
13556                 *handle_class = mono_defaults.fieldhandle_class;
13557         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13558                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13559                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13560                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13561                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13562                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13563
13564                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13565                 MonoMethod *method;
13566
13567                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13568                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13569                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13570                         method = ((MonoReflectionMethod *)c->cb)->method;
13571                 else
13572                         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)));
13573
13574                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13575                 *handle_class = mono_defaults.methodhandle_class;
13576                 mono_metadata_free_type (type);
13577         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13578                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13579                 if (m->method_args) {
13580                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13581                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13582                         if (context) {
13583                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13584                                 mono_error_assert_ok (&error);
13585                         }
13586                 } else {
13587                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13588                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13589                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13590                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13591
13592                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13593                         MonoMethod *method;
13594
13595                         if (is_sre_method_builder (mono_object_class (m->mb)))
13596                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13597                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13598                                 method = ((MonoReflectionMethod *)m->mb)->method;
13599                         else
13600                                 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)));
13601
13602                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13603                         mono_metadata_free_type (type);
13604                 }
13605                 *handle_class = mono_defaults.methodhandle_class;
13606         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13607                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13608                 MonoType *mtype;
13609                 MonoClass *klass;
13610                 MonoMethod *method;
13611                 gpointer iter;
13612                 char *name;
13613
13614                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13615                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13616                 klass = mono_class_from_mono_type (mtype);
13617
13618                 /* Find the method */
13619
13620                 name = mono_string_to_utf8 (m->name);
13621                 iter = NULL;
13622                 while ((method = mono_class_get_methods (klass, &iter))) {
13623                         if (!strcmp (method->name, name))
13624                                 break;
13625                 }
13626                 g_free (name);
13627
13628                 // FIXME:
13629                 g_assert (method);
13630                 // FIXME: Check parameters/return value etc. match
13631
13632                 result = method;
13633                 *handle_class = mono_defaults.methodhandle_class;
13634         } else if (is_sre_array (mono_object_get_class(obj)) ||
13635                                 is_sre_byref (mono_object_get_class(obj)) ||
13636                                 is_sre_pointer (mono_object_get_class(obj))) {
13637                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13638                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13639                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13640
13641                 if (context) {
13642                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13643                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13644
13645                         result = mono_class_from_mono_type (inflated);
13646                         mono_metadata_free_type (inflated);
13647                 } else {
13648                         result = mono_class_from_mono_type (type);
13649                 }
13650                 *handle_class = mono_defaults.typehandle_class;
13651         } else {
13652                 g_print ("%s\n", obj->vtable->klass->name);
13653                 g_assert_not_reached ();
13654         }
13655         return result;
13656 }
13657
13658 #else /* DISABLE_REFLECTION_EMIT */
13659
13660 MonoArray*
13661 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13662 {
13663         g_assert_not_reached ();
13664         return NULL;
13665 }
13666
13667 void
13668 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13669 {
13670         g_assert_not_reached ();
13671 }
13672
13673 void
13674 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13675 {
13676         g_assert_not_reached ();
13677 }
13678
13679 void
13680 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13681 {
13682         g_assert_not_reached ();
13683 }
13684
13685 void
13686 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13687 {
13688         g_assert_not_reached ();
13689 }
13690
13691 void
13692 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13693 {
13694         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13695 }
13696
13697 void
13698 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13699 {
13700         g_assert_not_reached ();
13701 }
13702
13703 void
13704 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13705 {
13706         g_assert_not_reached ();
13707 }
13708
13709 MonoReflectionModule *
13710 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13711 {
13712         g_assert_not_reached ();
13713         return NULL;
13714 }
13715
13716 guint32
13717 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13718 {
13719         g_assert_not_reached ();
13720         return 0;
13721 }
13722
13723 guint32
13724 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13725 {
13726         g_assert_not_reached ();
13727         return 0;
13728 }
13729
13730 guint32
13731 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13732                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13733 {
13734         g_assert_not_reached ();
13735         return 0;
13736 }
13737
13738 void
13739 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13740 {
13741 }
13742
13743 void
13744 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13745 {
13746         g_assert_not_reached ();
13747 }
13748
13749 void
13750 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13751 {
13752         *overrides = NULL;
13753         *num_overrides = 0;
13754 }
13755
13756 MonoReflectionEvent *
13757 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13758 {
13759         g_assert_not_reached ();
13760         return NULL;
13761 }
13762
13763 MonoReflectionType*
13764 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13765 {
13766         g_assert_not_reached ();
13767         return NULL;
13768 }
13769
13770 void
13771 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13772 {
13773         g_assert_not_reached ();
13774 }
13775
13776 MonoArray *
13777 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13778 {
13779         g_assert_not_reached ();
13780         return NULL;
13781 }
13782
13783 MonoArray *
13784 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13785 {
13786         g_assert_not_reached ();
13787         return NULL;
13788 }
13789
13790 void 
13791 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13792 {
13793 }
13794
13795 gpointer
13796 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13797 {
13798         return NULL;
13799 }
13800
13801 MonoType*
13802 mono_reflection_type_get_handle (MonoReflectionType* ref)
13803 {
13804         if (!ref)
13805                 return NULL;
13806         return ref->type;
13807 }
13808
13809 void
13810 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13811 {
13812         g_assert_not_reached ();
13813 }
13814
13815 #endif /* DISABLE_REFLECTION_EMIT */
13816
13817 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13818 const static guint32 declsec_flags_map[] = {
13819         0x00000000,                                     /* empty */
13820         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13821         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13822         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13823         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13824         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13825         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13826         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13827         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13828         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13829         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13830         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13831         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13832         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13833         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13834         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13835         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13836         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13837         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13838 };
13839
13840 /*
13841  * Returns flags that includes all available security action associated to the handle.
13842  * @token: metadata token (either for a class or a method)
13843  * @image: image where resides the metadata.
13844  */
13845 static guint32
13846 mono_declsec_get_flags (MonoImage *image, guint32 token)
13847 {
13848         int index = mono_metadata_declsec_from_index (image, token);
13849         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13850         guint32 result = 0;
13851         guint32 action;
13852         int i;
13853
13854         /* HasSecurity can be present for other, not specially encoded, attributes,
13855            e.g. SuppressUnmanagedCodeSecurityAttribute */
13856         if (index < 0)
13857                 return 0;
13858
13859         for (i = index; i < t->rows; i++) {
13860                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13861
13862                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13863                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13864                         break;
13865
13866                 action = cols [MONO_DECL_SECURITY_ACTION];
13867                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13868                         result |= declsec_flags_map [action];
13869                 } else {
13870                         g_assert_not_reached ();
13871                 }
13872         }
13873         return result;
13874 }
13875
13876 /*
13877  * Get the security actions (in the form of flags) associated with the specified method.
13878  *
13879  * @method: The method for which we want the declarative security flags.
13880  * Return the declarative security flags for the method (only).
13881  *
13882  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13883  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13884  */
13885 guint32
13886 mono_declsec_flags_from_method (MonoMethod *method)
13887 {
13888         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13889                 /* FIXME: No cache (for the moment) */
13890                 guint32 idx = mono_method_get_index (method);
13891                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13892                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13893                 return mono_declsec_get_flags (method->klass->image, idx);
13894         }
13895         return 0;
13896 }
13897
13898 /*
13899  * Get the security actions (in the form of flags) associated with the specified class.
13900  *
13901  * @klass: The class for which we want the declarative security flags.
13902  * Return the declarative security flags for the class.
13903  *
13904  * Note: We cache the flags inside the MonoClass structure as this will get 
13905  *       called very often (at least for each method).
13906  */
13907 guint32
13908 mono_declsec_flags_from_class (MonoClass *klass)
13909 {
13910         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13911                 if (!klass->ext || !klass->ext->declsec_flags) {
13912                         guint32 idx;
13913
13914                         idx = mono_metadata_token_index (klass->type_token);
13915                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13916                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13917                         mono_loader_lock ();
13918                         mono_class_alloc_ext (klass);
13919                         mono_loader_unlock ();
13920                         /* we cache the flags on classes */
13921                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13922                 }
13923                 return klass->ext->declsec_flags;
13924         }
13925         return 0;
13926 }
13927
13928 /*
13929  * Get the security actions (in the form of flags) associated with the specified assembly.
13930  *
13931  * @assembly: The assembly for which we want the declarative security flags.
13932  * Return the declarative security flags for the assembly.
13933  */
13934 guint32
13935 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13936 {
13937         guint32 idx = 1; /* there is only one assembly */
13938         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13939         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13940         return mono_declsec_get_flags (assembly->image, idx);
13941 }
13942
13943
13944 /*
13945  * Fill actions for the specific index (which may either be an encoded class token or
13946  * an encoded method token) from the metadata image.
13947  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13948  */
13949 static MonoBoolean
13950 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13951         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13952 {
13953         MonoBoolean result = FALSE;
13954         MonoTableInfo *t;
13955         guint32 cols [MONO_DECL_SECURITY_SIZE];
13956         int index = mono_metadata_declsec_from_index (image, token);
13957         int i;
13958
13959         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13960         for (i = index; i < t->rows; i++) {
13961                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13962
13963                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13964                         return result;
13965
13966                 /* if present only replace (class) permissions with method permissions */
13967                 /* if empty accept either class or method permissions */
13968                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13969                         if (!actions->demand.blob) {
13970                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13971                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13972                                 actions->demand.blob = (char*) (blob + 2);
13973                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13974                                 result = TRUE;
13975                         }
13976                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13977                         if (!actions->noncasdemand.blob) {
13978                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13979                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13980                                 actions->noncasdemand.blob = (char*) (blob + 2);
13981                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13982                                 result = TRUE;
13983                         }
13984                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13985                         if (!actions->demandchoice.blob) {
13986                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13987                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13988                                 actions->demandchoice.blob = (char*) (blob + 2);
13989                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13990                                 result = TRUE;
13991                         }
13992                 }
13993         }
13994
13995         return result;
13996 }
13997
13998 static MonoBoolean
13999 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14000         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14001 {
14002         guint32 idx = mono_metadata_token_index (klass->type_token);
14003         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14004         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14005         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14006 }
14007
14008 static MonoBoolean
14009 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14010         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14011 {
14012         guint32 idx = mono_method_get_index (method);
14013         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14014         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14015         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14016 }
14017
14018 /*
14019  * Collect all actions (that requires to generate code in mini) assigned for
14020  * the specified method.
14021  * Note: Don't use the content of actions if the function return FALSE.
14022  */
14023 MonoBoolean
14024 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14025 {
14026         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14027                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14028         MonoBoolean result = FALSE;
14029         guint32 flags;
14030
14031         /* quick exit if no declarative security is present in the metadata */
14032         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14033                 return FALSE;
14034
14035         /* we want the original as the wrapper is "free" of the security informations */
14036         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14037                 method = mono_marshal_method_from_wrapper (method);
14038                 if (!method)
14039                         return FALSE;
14040         }
14041
14042         /* First we look for method-level attributes */
14043         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14044                 mono_class_init (method->klass);
14045                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14046
14047                 result = mono_declsec_get_method_demands_params (method, demands, 
14048                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14049         }
14050
14051         /* Here we use (or create) the class declarative cache to look for demands */
14052         flags = mono_declsec_flags_from_class (method->klass);
14053         if (flags & mask) {
14054                 if (!result) {
14055                         mono_class_init (method->klass);
14056                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14057                 }
14058                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14059                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14060         }
14061
14062         /* The boolean return value is used as a shortcut in case nothing needs to
14063            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14064         return result;
14065 }
14066
14067
14068 /*
14069  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14070  *
14071  * Note: Don't use the content of actions if the function return FALSE.
14072  */
14073 MonoBoolean
14074 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14075 {
14076         MonoBoolean result = FALSE;
14077         guint32 flags;
14078
14079         /* quick exit if no declarative security is present in the metadata */
14080         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14081                 return FALSE;
14082
14083         /* we want the original as the wrapper is "free" of the security informations */
14084         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14085                 method = mono_marshal_method_from_wrapper (method);
14086                 if (!method)
14087                         return FALSE;
14088         }
14089
14090         /* results are independant - zeroize both */
14091         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14092         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14093
14094         /* First we look for method-level attributes */
14095         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14096                 mono_class_init (method->klass);
14097
14098                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14099                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14100         }
14101
14102         /* Here we use (or create) the class declarative cache to look for demands */
14103         flags = mono_declsec_flags_from_class (method->klass);
14104         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14105                 mono_class_init (method->klass);
14106
14107                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14108                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14109         }
14110
14111         return result;
14112 }
14113
14114 /*
14115  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14116  *
14117  * @klass       The inherited class - this is the class that provides the security check (attributes)
14118  * @demans      
14119  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14120  * 
14121  * Note: Don't use the content of actions if the function return FALSE.
14122  */
14123 MonoBoolean
14124 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14125 {
14126         MonoBoolean result = FALSE;
14127         guint32 flags;
14128
14129         /* quick exit if no declarative security is present in the metadata */
14130         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14131                 return FALSE;
14132
14133         /* Here we use (or create) the class declarative cache to look for demands */
14134         flags = mono_declsec_flags_from_class (klass);
14135         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14136                 mono_class_init (klass);
14137                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14138
14139                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14140                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14141         }
14142
14143         return result;
14144 }
14145
14146 /*
14147  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14148  *
14149  * Note: Don't use the content of actions if the function return FALSE.
14150  */
14151 MonoBoolean
14152 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14153 {
14154         /* quick exit if no declarative security is present in the metadata */
14155         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14156                 return FALSE;
14157
14158         /* we want the original as the wrapper is "free" of the security informations */
14159         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14160                 method = mono_marshal_method_from_wrapper (method);
14161                 if (!method)
14162                         return FALSE;
14163         }
14164
14165         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14166                 mono_class_init (method->klass);
14167                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14168
14169                 return mono_declsec_get_method_demands_params (method, demands, 
14170                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14171         }
14172         return FALSE;
14173 }
14174
14175
14176 static MonoBoolean
14177 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14178 {
14179         guint32 cols [MONO_DECL_SECURITY_SIZE];
14180         MonoTableInfo *t;
14181         int i;
14182
14183         int index = mono_metadata_declsec_from_index (image, token);
14184         if (index == -1)
14185                 return FALSE;
14186
14187         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14188         for (i = index; i < t->rows; i++) {
14189                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14190
14191                 /* shortcut - index are ordered */
14192                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14193                         return FALSE;
14194
14195                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14196                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14197                         entry->blob = (char*) (metadata + 2);
14198                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14199                         return TRUE;
14200                 }
14201         }
14202
14203         return FALSE;
14204 }
14205
14206 MonoBoolean
14207 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14208 {
14209         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14210                 guint32 idx = mono_method_get_index (method);
14211                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14212                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14213                 return get_declsec_action (method->klass->image, idx, action, entry);
14214         }
14215         return FALSE;
14216 }
14217
14218 MonoBoolean
14219 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14220 {
14221         /* use cache */
14222         guint32 flags = mono_declsec_flags_from_class (klass);
14223         if (declsec_flags_map [action] & flags) {
14224                 guint32 idx = mono_metadata_token_index (klass->type_token);
14225                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14226                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14227                 return get_declsec_action (klass->image, idx, action, entry);
14228         }
14229         return FALSE;
14230 }
14231
14232 MonoBoolean
14233 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14234 {
14235         guint32 idx = 1; /* there is only one assembly */
14236         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14237         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14238
14239         return get_declsec_action (assembly->image, idx, action, entry);
14240 }
14241
14242 gboolean
14243 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14244 {
14245         MonoError error;
14246         MonoObject *res, *exc;
14247         void *params [1];
14248         static MonoMethod *method = NULL;
14249
14250         if (method == NULL) {
14251                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14252                 g_assert (method);
14253         }
14254
14255         /* 
14256          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14257          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14258          */
14259         g_assert (mono_class_get_ref_info (klass));
14260         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14261
14262         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14263         mono_error_raise_exception (&error); /* FIXME don't raise here */
14264
14265         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14266
14267         if (exc || !mono_error_ok (&error)) {
14268                 mono_error_cleanup (&error);
14269                 return FALSE;
14270         } else
14271                 return *(MonoBoolean*)mono_object_unbox (res);
14272 }
14273
14274 /**
14275  * mono_reflection_type_get_type:
14276  * @reftype: the System.Type object
14277  *
14278  * Returns the MonoType* associated with the C# System.Type object @reftype.
14279  */
14280 MonoType*
14281 mono_reflection_type_get_type (MonoReflectionType *reftype)
14282 {
14283         g_assert (reftype);
14284
14285         MonoError error;
14286         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14287         mono_error_assert_ok (&error);
14288         return result;
14289 }
14290
14291 /**
14292  * mono_reflection_assembly_get_assembly:
14293  * @refassembly: the System.Reflection.Assembly object
14294  *
14295  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14296  */
14297 MonoAssembly*
14298 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14299 {
14300         g_assert (refassembly);
14301
14302         return refassembly->assembly;
14303 }
14304