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