[SRE] MonoError in create_generic_typespec
[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, MonoError *error);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 /**
428  * image_g_free:
429  * @image: a MonoImage
430  * @ptr: pointer
431  *
432  * If @image is NULL, free @ptr, otherwise do nothing.
433  */
434 static void
435 image_g_free (MonoImage *image, gpointer ptr)
436 {
437         if (image == NULL)
438                 g_free (ptr);
439 }
440
441 #ifndef DISABLE_REFLECTION_EMIT
442 static char*
443 image_strdup (MonoImage *image, const char *s)
444 {
445         MONO_REQ_GC_NEUTRAL_MODE;
446
447         if (image)
448                 return mono_image_strdup (image, s);
449         else
450                 return g_strdup (s);
451 }
452 #endif
453
454 #define image_g_new(image,struct_type, n_structs)               \
455     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
456
457 #define image_g_new0(image,struct_type, n_structs)              \
458     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460
461 static void
462 alloc_table (MonoDynamicTable *table, guint nrows)
463 {
464         MONO_REQ_GC_NEUTRAL_MODE;
465
466         table->rows = nrows;
467         g_assert (table->columns);
468         if (nrows + 1 >= table->alloc_rows) {
469                 while (nrows + 1 >= table->alloc_rows) {
470                         if (table->alloc_rows == 0)
471                                 table->alloc_rows = 16;
472                         else
473                                 table->alloc_rows *= 2;
474                 }
475
476                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
477         }
478 }
479
480 static void
481 make_room_in_stream (MonoDynamicStream *stream, int size)
482 {
483         MONO_REQ_GC_NEUTRAL_MODE;
484
485         if (size <= stream->alloc_size)
486                 return;
487         
488         while (stream->alloc_size <= size) {
489                 if (stream->alloc_size < 4096)
490                         stream->alloc_size = 4096;
491                 else
492                         stream->alloc_size *= 2;
493         }
494         
495         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
496 }
497
498 static guint32
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
500 {
501         MONO_REQ_GC_NEUTRAL_MODE;
502
503         guint32 idx;
504         guint32 len;
505         gpointer oldkey, oldval;
506
507         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508                 return GPOINTER_TO_UINT (oldval);
509
510         len = strlen (str) + 1;
511         idx = sh->index;
512         
513         make_room_in_stream (sh, idx + len);
514
515         /*
516          * We strdup the string even if we already copy them in sh->data
517          * so that the string pointers in the hash remain valid even if
518          * we need to realloc sh->data. We may want to avoid that later.
519          */
520         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521         memcpy (sh->data + idx, str, len);
522         sh->index += len;
523         return idx;
524 }
525
526 static guint32
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
528 {
529         MONO_REQ_GC_UNSAFE_MODE;
530
531         char *name = mono_string_to_utf8 (str);
532         guint32 idx;
533         idx = string_heap_insert (sh, name);
534         g_free (name);
535         return idx;
536 }
537
538 #ifndef DISABLE_REFLECTION_EMIT
539 static void
540 string_heap_init (MonoDynamicStream *sh)
541 {
542         MONO_REQ_GC_NEUTRAL_MODE;
543
544         sh->index = 0;
545         sh->alloc_size = 4096;
546         sh->data = (char *)g_malloc (4096);
547         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548         string_heap_insert (sh, "");
549 }
550 #endif
551
552 static guint32
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
554 {
555         MONO_REQ_GC_NEUTRAL_MODE;
556
557         guint32 idx;
558         
559         make_room_in_stream (stream, stream->index + len);
560         memcpy (stream->data + stream->index, data, len);
561         idx = stream->index;
562         stream->index += len;
563         /* 
564          * align index? Not without adding an additional param that controls it since
565          * we may store a blob value in pieces.
566          */
567         return idx;
568 }
569
570 static guint32
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         guint32 idx;
576         
577         make_room_in_stream (stream, stream->index + len);
578         memset (stream->data + stream->index, 0, len);
579         idx = stream->index;
580         stream->index += len;
581         return idx;
582 }
583
584 static void
585 stream_data_align (MonoDynamicStream *stream)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         char buf [4] = {0};
590         guint32 count = stream->index % 4;
591
592         /* we assume the stream data will be aligned */
593         if (count)
594                 mono_image_add_stream_data (stream, buf, 4 - count);
595 }
596
597 #ifndef DISABLE_REFLECTION_EMIT
598 static int
599 mono_blob_entry_hash (const char* str)
600 {
601         MONO_REQ_GC_NEUTRAL_MODE;
602
603         guint len, h;
604         const char *end;
605         len = mono_metadata_decode_blob_size (str, &str);
606         if (len > 0) {
607                 end = str + len;
608                 h = *str;
609                 for (str += 1; str < end; str++)
610                         h = (h << 5) - h + *str;
611                 return h;
612         } else {
613                 return 0;
614         }
615 }
616
617 static gboolean
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619         MONO_REQ_GC_NEUTRAL_MODE;
620
621         int len, len2;
622         const char *end1;
623         const char *end2;
624         len = mono_metadata_decode_blob_size (str1, &end1);
625         len2 = mono_metadata_decode_blob_size (str2, &end2);
626         if (len != len2)
627                 return 0;
628         return memcmp (end1, end2, len) == 0;
629 }
630 #endif
631 static guint32
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
633 {
634         MONO_REQ_GC_NEUTRAL_MODE;
635
636         guint32 idx;
637         char *copy;
638         gpointer oldkey, oldval;
639
640         copy = (char *)g_malloc (s1+s2);
641         memcpy (copy, b1, s1);
642         memcpy (copy + s1, b2, s2);
643         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
644                 g_free (copy);
645                 idx = GPOINTER_TO_UINT (oldval);
646         } else {
647                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648                 mono_image_add_stream_data (&assembly->blob, b2, s2);
649                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
650         }
651         return idx;
652 }
653
654 static guint32
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
656 {
657         MONO_REQ_GC_NEUTRAL_MODE;
658
659         char blob_size [8];
660         char *b = blob_size;
661         guint32 size = buf->p - buf->buf;
662         /* store length */
663         g_assert (size <= (buf->end - buf->buf));
664         mono_metadata_encode_value (size, b, &b);
665         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
666 }
667
668 /*
669  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670  * dest may be misaligned.
671  */
672 static void
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674         MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
676         int elem;
677
678         for (elem = 0; elem < nelem; ++elem) {
679                 switch (len) {
680                 case 1:
681                         *dest = *val;
682                         break;
683                 case 2:
684                         dest [0] = val [1];
685                         dest [1] = val [0];
686                         break;
687                 case 4:
688                         dest [0] = val [3];
689                         dest [1] = val [2];
690                         dest [2] = val [1];
691                         dest [3] = val [0];
692                         break;
693                 case 8:
694                         dest [0] = val [7];
695                         dest [1] = val [6];
696                         dest [2] = val [5];
697                         dest [3] = val [4];
698                         dest [4] = val [3];
699                         dest [5] = val [2];
700                         dest [6] = val [1];
701                         dest [7] = val [0];
702                         break;
703                 default:
704                         g_assert_not_reached ();
705                 }
706                 dest += len;
707                 val += len;
708         }
709 #else
710         memcpy (dest, val, len * nelem);
711 #endif
712 }
713
714 static guint32
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718         
719         char blob_size [64];
720         char *b = blob_size;
721         guint32 idx = 0, len;
722
723         len = str->length * 2;
724         mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
726         {
727                 char *swapped = g_malloc (2 * mono_string_length (str));
728                 const char *p = (const char*)mono_string_chars (str);
729
730                 swap_with_size (swapped, p, 2, mono_string_length (str));
731                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
732                 g_free (swapped);
733         }
734 #else
735         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
736 #endif
737         return idx;
738 }
739
740 #ifndef DISABLE_REFLECTION_EMIT
741 static MonoClass *
742 default_class_from_mono_type (MonoType *type)
743 {
744         MONO_REQ_GC_NEUTRAL_MODE;
745
746         switch (type->type) {
747         case MONO_TYPE_OBJECT:
748                 return mono_defaults.object_class;
749         case MONO_TYPE_VOID:
750                 return mono_defaults.void_class;
751         case MONO_TYPE_BOOLEAN:
752                 return mono_defaults.boolean_class;
753         case MONO_TYPE_CHAR:
754                 return mono_defaults.char_class;
755         case MONO_TYPE_I1:
756                 return mono_defaults.sbyte_class;
757         case MONO_TYPE_U1:
758                 return mono_defaults.byte_class;
759         case MONO_TYPE_I2:
760                 return mono_defaults.int16_class;
761         case MONO_TYPE_U2:
762                 return mono_defaults.uint16_class;
763         case MONO_TYPE_I4:
764                 return mono_defaults.int32_class;
765         case MONO_TYPE_U4:
766                 return mono_defaults.uint32_class;
767         case MONO_TYPE_I:
768                 return mono_defaults.int_class;
769         case MONO_TYPE_U:
770                 return mono_defaults.uint_class;
771         case MONO_TYPE_I8:
772                 return mono_defaults.int64_class;
773         case MONO_TYPE_U8:
774                 return mono_defaults.uint64_class;
775         case MONO_TYPE_R4:
776                 return mono_defaults.single_class;
777         case MONO_TYPE_R8:
778                 return mono_defaults.double_class;
779         case MONO_TYPE_STRING:
780                 return mono_defaults.string_class;
781         default:
782                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783                 g_assert_not_reached ();
784         }
785         
786         return NULL;
787 }
788 #endif
789
790 /*
791  * mono_class_get_ref_info:
792  *
793  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
794  */
795 gpointer
796 mono_class_get_ref_info (MonoClass *klass)
797 {
798         MONO_REQ_GC_UNSAFE_MODE;
799
800         if (klass->ref_info_handle == 0)
801                 return NULL;
802         else
803                 return mono_gchandle_get_target (klass->ref_info_handle);
804 }
805
806 void
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
808 {
809         MONO_REQ_GC_UNSAFE_MODE;
810
811         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812         g_assert (klass->ref_info_handle != 0);
813 }
814
815 void
816 mono_class_free_ref_info (MonoClass *klass)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (klass->ref_info_handle) {
821                 mono_gchandle_free (klass->ref_info_handle);
822                 klass->ref_info_handle = 0;
823         }
824 }
825
826 static void
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
828 {
829         MONO_REQ_GC_NEUTRAL_MODE;
830
831         int i;
832         MonoGenericInst *class_inst;
833         MonoClass *klass;
834
835         g_assert (gclass);
836
837         class_inst = gclass->context.class_inst;
838
839         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840         klass = gclass->container_class;
841         sigbuffer_add_value (buf, klass->byval_arg.type);
842         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
843
844         sigbuffer_add_value (buf, class_inst->type_argc);
845         for (i = 0; i < class_inst->type_argc; ++i)
846                 encode_type (assembly, class_inst->type_argv [i], buf);
847
848 }
849
850 static void
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
852 {
853         MONO_REQ_GC_NEUTRAL_MODE;
854
855         if (!type) {
856                 g_assert_not_reached ();
857                 return;
858         }
859                 
860         if (type->byref)
861                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
862
863         switch (type->type){
864         case MONO_TYPE_VOID:
865         case MONO_TYPE_BOOLEAN:
866         case MONO_TYPE_CHAR:
867         case MONO_TYPE_I1:
868         case MONO_TYPE_U1:
869         case MONO_TYPE_I2:
870         case MONO_TYPE_U2:
871         case MONO_TYPE_I4:
872         case MONO_TYPE_U4:
873         case MONO_TYPE_I8:
874         case MONO_TYPE_U8:
875         case MONO_TYPE_R4:
876         case MONO_TYPE_R8:
877         case MONO_TYPE_I:
878         case MONO_TYPE_U:
879         case MONO_TYPE_STRING:
880         case MONO_TYPE_OBJECT:
881         case MONO_TYPE_TYPEDBYREF:
882                 sigbuffer_add_value (buf, type->type);
883                 break;
884         case MONO_TYPE_PTR:
885                 sigbuffer_add_value (buf, type->type);
886                 encode_type (assembly, type->data.type, buf);
887                 break;
888         case MONO_TYPE_SZARRAY:
889                 sigbuffer_add_value (buf, type->type);
890                 encode_type (assembly, &type->data.klass->byval_arg, buf);
891                 break;
892         case MONO_TYPE_VALUETYPE:
893         case MONO_TYPE_CLASS: {
894                 MonoClass *k = mono_class_from_mono_type (type);
895
896                 if (k->generic_container) {
897                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898                         encode_generic_class (assembly, gclass, buf);
899                 } else {
900                         /*
901                          * Make sure we use the correct type.
902                          */
903                         sigbuffer_add_value (buf, k->byval_arg.type);
904                         /*
905                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906                          * otherwise two typerefs could point to the same type, leading to
907                          * verification errors.
908                          */
909                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
910                 }
911                 break;
912         }
913         case MONO_TYPE_ARRAY:
914                 sigbuffer_add_value (buf, type->type);
915                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916                 sigbuffer_add_value (buf, type->data.array->rank);
917                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918                 sigbuffer_add_value (buf, 0);
919                 break;
920         case MONO_TYPE_GENERICINST:
921                 encode_generic_class (assembly, type->data.generic_class, buf);
922                 break;
923         case MONO_TYPE_VAR:
924         case MONO_TYPE_MVAR:
925                 sigbuffer_add_value (buf, type->type);
926                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
927                 break;
928         default:
929                 g_error ("need to encode type %x", type->type);
930         }
931 }
932
933 static void
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
935 {
936         MONO_REQ_GC_UNSAFE_MODE;
937
938         mono_error_init (error);
939
940         if (!type) {
941                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
942                 return;
943         }
944
945         MonoType *t = mono_reflection_type_get_handle (type, error);
946         return_if_nok (error);
947         encode_type (assembly, t, buf);
948 }
949
950 static void
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
952 {
953         MONO_REQ_GC_UNSAFE_MODE;
954
955         int i;
956
957         mono_error_init (error);
958
959         if (modreq) {
960                 for (i = 0; i < mono_array_length (modreq); ++i) {
961                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962                         return_if_nok (error);
963                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
965                 }
966         }
967         if (modopt) {
968                 for (i = 0; i < mono_array_length (modopt); ++i) {
969                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970                         return_if_nok (error);
971                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973                 }
974         }
975 }
976
977 #ifndef DISABLE_REFLECTION_EMIT
978 static guint32
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
980 {
981         MONO_REQ_GC_UNSAFE_MODE;
982
983         SigBuffer buf;
984         int i;
985         guint32 nparams =  sig->param_count;
986         guint32 idx;
987
988         if (!assembly->save)
989                 return 0;
990
991         sigbuffer_init (&buf, 32);
992         /*
993          * FIXME: vararg, explicit_this, differenc call_conv values...
994          */
995         idx = sig->call_convention;
996         if (sig->hasthis)
997                 idx |= 0x20; /* hasthis */
998         if (sig->generic_param_count)
999                 idx |= 0x10; /* generic */
1000         sigbuffer_add_byte (&buf, idx);
1001         if (sig->generic_param_count)
1002                 sigbuffer_add_value (&buf, sig->generic_param_count);
1003         sigbuffer_add_value (&buf, nparams);
1004         encode_type (assembly, sig->ret, &buf);
1005         for (i = 0; i < nparams; ++i) {
1006                 if (i == sig->sentinelpos)
1007                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008                 encode_type (assembly, sig->params [i], &buf);
1009         }
1010         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011         sigbuffer_free (&buf);
1012         return idx;
1013 }
1014 #endif
1015
1016 static guint32
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1018 {
1019         MONO_REQ_GC_UNSAFE_MODE;
1020
1021         mono_error_init (error);
1022
1023         /*
1024          * FIXME: reuse code from method_encode_signature().
1025          */
1026         SigBuffer buf;
1027         int i;
1028         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1029         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1031         guint32 idx;
1032
1033         sigbuffer_init (&buf, 32);
1034         /* LAMESPEC: all the call conv spec is foobared */
1035         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036         if (mb->call_conv & 2)
1037                 idx |= 0x5; /* vararg */
1038         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039                 idx |= 0x20; /* hasthis */
1040         if (ngparams)
1041                 idx |= 0x10; /* generic */
1042         sigbuffer_add_byte (&buf, idx);
1043         if (ngparams)
1044                 sigbuffer_add_value (&buf, ngparams);
1045         sigbuffer_add_value (&buf, nparams + notypes);
1046         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1047         if (!is_ok (error))
1048                 goto leave;
1049         encode_reflection_type (assembly, mb->rtype, &buf, error);
1050         if (!is_ok (error))
1051                 goto leave;
1052         for (i = 0; i < nparams; ++i) {
1053                 MonoArray *modreq = NULL;
1054                 MonoArray *modopt = NULL;
1055                 MonoReflectionType *pt;
1056
1057                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1062                 if (!is_ok (error))
1063                         goto leave;
1064                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065                 encode_reflection_type (assembly, pt, &buf, error);
1066                 if (!is_ok (error))
1067                         goto leave;
1068         }
1069         if (notypes)
1070                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071         for (i = 0; i < notypes; ++i) {
1072                 MonoReflectionType *pt;
1073
1074                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075                 encode_reflection_type (assembly, pt, &buf, error);
1076                 if (!is_ok (error))
1077                         goto leave;
1078         }
1079
1080         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1081 leave:
1082         sigbuffer_free (&buf);
1083         return idx;
1084 }
1085
1086 static guint32
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1088 {
1089         MONO_REQ_GC_UNSAFE_MODE;
1090
1091         mono_error_init (error);
1092
1093         MonoDynamicTable *table;
1094         guint32 *values;
1095         guint32 idx, sig_idx;
1096         guint nl = mono_array_length (ilgen->locals);
1097         SigBuffer buf;
1098         int i;
1099
1100         sigbuffer_init (&buf, 32);
1101         sigbuffer_add_value (&buf, 0x07);
1102         sigbuffer_add_value (&buf, nl);
1103         for (i = 0; i < nl; ++i) {
1104                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1105                 
1106                 if (lb->is_pinned)
1107                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1108                 
1109                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110                 if (!is_ok (error)) {
1111                         sigbuffer_free (&buf);
1112                         return 0;
1113                 }
1114         }
1115         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116         sigbuffer_free (&buf);
1117
1118         if (assembly->standalonesig_cache == NULL)
1119                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1121         if (idx)
1122                 return idx;
1123
1124         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125         idx = table->next_idx ++;
1126         table->rows ++;
1127         alloc_table (table, table->rows);
1128         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1129
1130         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1131
1132         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1133
1134         return idx;
1135 }
1136
1137 static guint32
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1139 {
1140         MONO_REQ_GC_UNSAFE_MODE;
1141
1142         guint32 num_clauses = 0;
1143         int i;
1144
1145         MonoILExceptionInfo *ex_info;
1146         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148                 if (ex_info->handlers)
1149                         num_clauses += mono_array_length (ex_info->handlers);
1150                 else
1151                         num_clauses++;
1152         }
1153
1154         return num_clauses;
1155 }
1156
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1160 {
1161         MONO_REQ_GC_UNSAFE_MODE;
1162
1163         mono_error_init (error);
1164
1165         MonoExceptionClause *clauses;
1166         MonoExceptionClause *clause;
1167         MonoILExceptionInfo *ex_info;
1168         MonoILExceptionBlock *ex_block;
1169         guint32 finally_start;
1170         int i, j, clause_index;;
1171
1172         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1173
1174         clause_index = 0;
1175         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177                 finally_start = ex_info->start + ex_info->len;
1178                 if (!ex_info->handlers)
1179                         continue;
1180                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182                         clause = &(clauses [clause_index]);
1183
1184                         clause->flags = ex_block->type;
1185                         clause->try_offset = ex_info->start;
1186
1187                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188                                 clause->try_len = finally_start - ex_info->start;
1189                         else
1190                                 clause->try_len = ex_info->len;
1191                         clause->handler_offset = ex_block->start;
1192                         clause->handler_len = ex_block->len;
1193                         if (ex_block->extype) {
1194                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1195
1196                                 if (!is_ok (error)) {
1197                                         image_g_free (image, clauses);
1198                                         return NULL;
1199                                 }
1200                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1201                         } else {
1202                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203                                         clause->data.filter_offset = ex_block->filter_offset;
1204                                 else
1205                                         clause->data.filter_offset = 0;
1206                         }
1207                         finally_start = ex_block->start + ex_block->len;
1208
1209                         clause_index ++;
1210                 }
1211         }
1212
1213         return clauses;
1214 }
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1216
1217 /**
1218  * method_encode_code:
1219  *
1220  * @assembly the assembly
1221  * @mb the managed MethodBuilder
1222  * @error set on error
1223  *
1224  * Note that the return value is not sensible if @error is set.
1225  */
1226 static guint32
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1228 {
1229         MONO_REQ_GC_UNSAFE_MODE;
1230
1231         char flags = 0;
1232         guint32 idx;
1233         guint32 code_size;
1234         gint32 max_stack, i;
1235         gint32 num_locals = 0;
1236         gint32 num_exception = 0;
1237         gint maybe_small;
1238         guint32 fat_flags;
1239         char fat_header [12];
1240         guint32 int_value;
1241         guint16 short_value;
1242         guint32 local_sig = 0;
1243         guint32 header_size = 12;
1244         MonoArray *code;
1245
1246         mono_error_init (error);
1247
1248         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1250                 return 0;
1251
1252         /*if (mb->name)
1253                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1254         if (mb->ilgen) {
1255                 code = mb->ilgen->code;
1256                 code_size = mb->ilgen->code_len;
1257                 max_stack = mb->ilgen->max_stack;
1258                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259                 if (mb->ilgen->ex_handlers)
1260                         num_exception = method_count_clauses (mb->ilgen);
1261         } else {
1262                 code = mb->code;
1263                 if (code == NULL){
1264                         char *name = mono_string_to_utf8 (mb->name);
1265                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1267                         g_free (str);
1268                         g_free (name);
1269                         return 0;
1270                 }
1271
1272                 code_size = mono_array_length (code);
1273                 max_stack = 8; /* we probably need to run a verifier on the code... */
1274         }
1275
1276         stream_data_align (&assembly->code);
1277
1278         /* check for exceptions, maxstack, locals */
1279         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1280         if (maybe_small) {
1281                 if (code_size < 64 && !(code_size & 1)) {
1282                         flags = (code_size << 2) | 0x2;
1283                 } else if (code_size < 32 && (code_size & 1)) {
1284                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1285                 } else {
1286                         goto fat_header;
1287                 }
1288                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289                 /* add to the fixup todo list */
1290                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293                 return assembly->text_rva + idx;
1294         } 
1295 fat_header:
1296         if (num_locals) {
1297                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298                 return_val_if_nok (error, 0);
1299         }
1300         /* 
1301          * FIXME: need to set also the header size in fat_flags.
1302          * (and more sects and init locals flags)
1303          */
1304         fat_flags =  0x03;
1305         if (num_exception)
1306                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307         if (mb->init_locals)
1308                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309         fat_header [0] = fat_flags;
1310         fat_header [1] = (header_size / 4 ) << 4;
1311         short_value = GUINT16_TO_LE (max_stack);
1312         memcpy (fat_header + 2, &short_value, 2);
1313         int_value = GUINT32_TO_LE (code_size);
1314         memcpy (fat_header + 4, &int_value, 4);
1315         int_value = GUINT32_TO_LE (local_sig);
1316         memcpy (fat_header + 8, &int_value, 4);
1317         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318         /* add to the fixup todo list */
1319         if (mb->ilgen && mb->ilgen->num_token_fixups)
1320                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1321         
1322         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323         if (num_exception) {
1324                 unsigned char sheader [4];
1325                 MonoILExceptionInfo * ex_info;
1326                 MonoILExceptionBlock * ex_block;
1327                 int j;
1328
1329                 stream_data_align (&assembly->code);
1330                 /* always use fat format for now */
1331                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332                 num_exception *= 6 * sizeof (guint32);
1333                 num_exception += 4; /* include the size of the header */
1334                 sheader [1] = num_exception & 0xff;
1335                 sheader [2] = (num_exception >> 8) & 0xff;
1336                 sheader [3] = (num_exception >> 16) & 0xff;
1337                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338                 /* fat header, so we are already aligned */
1339                 /* reverse order */
1340                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342                         if (ex_info->handlers) {
1343                                 int finally_start = ex_info->start + ex_info->len;
1344                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1345                                         guint32 val;
1346                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1347                                         /* the flags */
1348                                         val = GUINT32_TO_LE (ex_block->type);
1349                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1350                                         /* try offset */
1351                                         val = GUINT32_TO_LE (ex_info->start);
1352                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353                                         /* need fault, too, probably */
1354                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1356                                         else
1357                                                 val = GUINT32_TO_LE (ex_info->len);
1358                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359                                         /* handler offset */
1360                                         val = GUINT32_TO_LE (ex_block->start);
1361                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362                                         /* handler len */
1363                                         val = GUINT32_TO_LE (ex_block->len);
1364                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365                                         finally_start = ex_block->start + ex_block->len;
1366                                         if (ex_block->extype) {
1367                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368                                                 return_val_if_nok (error, 0);
1369
1370                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1371                                         } else {
1372                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373                                                         val = ex_block->filter_offset;
1374                                                 else
1375                                                         val = 0;
1376                                         }
1377                                         val = GUINT32_TO_LE (val);
1378                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1380                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1381                                 }
1382                         } else {
1383                                 g_error ("No clauses for ex info block %d", i);
1384                         }
1385                 }
1386         }
1387         return assembly->text_rva + idx;
1388 }
1389
1390 static guint32
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1392 {
1393         MONO_REQ_GC_NEUTRAL_MODE;
1394
1395         int i;
1396         MonoDynamicTable *table;
1397         guint32 *values;
1398         
1399         table = &assembly->tables [table_idx];
1400
1401         g_assert (col < table->columns);
1402
1403         values = table->values + table->columns;
1404         for (i = 1; i <= table->rows; ++i) {
1405                 if (values [col] == token)
1406                         return i;
1407                 values += table->columns;
1408         }
1409         return 0;
1410 }
1411
1412 /*
1413  * LOCKING: Acquires the loader lock. 
1414  */
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1417 {
1418         MONO_REQ_GC_NEUTRAL_MODE;
1419
1420         MonoCustomAttrInfo* res;
1421
1422         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1423
1424         if (!res)
1425                 return NULL;
1426
1427         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1428         res->cached = 0;
1429         return res;
1430 }
1431
1432 static gboolean
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1434 {
1435         MONO_REQ_GC_UNSAFE_MODE;
1436
1437         /* FIXME: Need to do more checks */
1438         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1440
1441                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1442                         return FALSE;
1443         }
1444
1445         return TRUE;
1446 }
1447
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1450 {
1451         MONO_REQ_GC_UNSAFE_MODE;
1452
1453         int i, index, count, not_visible;
1454         MonoCustomAttrInfo *ainfo;
1455         MonoReflectionCustomAttr *cattr;
1456
1457         if (!cattrs)
1458                 return NULL;
1459         /* FIXME: check in assembly the Run flag is set */
1460
1461         count = mono_array_length (cattrs);
1462
1463         /* Skip nonpublic attributes since MS.NET seems to do the same */
1464         /* FIXME: This needs to be done more globally */
1465         not_visible = 0;
1466         for (i = 0; i < count; ++i) {
1467                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468                 if (!custom_attr_visible (image, cattr))
1469                         not_visible ++;
1470         }
1471         count -= not_visible;
1472
1473         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1474
1475         ainfo->image = image;
1476         ainfo->num_attrs = count;
1477         ainfo->cached = alloc_img != NULL;
1478         index = 0;
1479         for (i = 0; i < count; ++i) {
1480                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481                 if (custom_attr_visible (image, cattr)) {
1482                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484                         ainfo->attrs [index].ctor = cattr->ctor->method;
1485                         ainfo->attrs [index].data = saved;
1486                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1487                         index ++;
1488                 }
1489         }
1490
1491         return ainfo;
1492 }
1493
1494 #ifndef DISABLE_REFLECTION_EMIT
1495 /*
1496  * LOCKING: Acquires the loader lock. 
1497  */
1498 static void
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1500 {
1501         MONO_REQ_GC_UNSAFE_MODE;
1502
1503         MonoCustomAttrInfo *ainfo, *tmp;
1504
1505         if (!cattrs || !mono_array_length (cattrs))
1506                 return;
1507
1508         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1509
1510         mono_loader_lock ();
1511         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1512         if (tmp)
1513                 mono_custom_attrs_free (tmp);
1514         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515         mono_loader_unlock ();
1516
1517 }
1518 #endif
1519
1520 void
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1522 {
1523         MONO_REQ_GC_NEUTRAL_MODE;
1524
1525         if (ainfo && !ainfo->cached)
1526                 g_free (ainfo);
1527 }
1528
1529 /*
1530  * idx is the table index of the object
1531  * type is one of MONO_CUSTOM_ATTR_*
1532  */
1533 static gboolean
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1535 {
1536         MONO_REQ_GC_UNSAFE_MODE;
1537
1538         MonoDynamicTable *table;
1539         MonoReflectionCustomAttr *cattr;
1540         guint32 *values;
1541         guint32 count, i, token;
1542         char blob_size [6];
1543         char *p = blob_size;
1544         
1545         mono_error_init (error);
1546
1547         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1548         if (!cattrs)
1549                 return TRUE;
1550         count = mono_array_length (cattrs);
1551         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552         table->rows += count;
1553         alloc_table (table, table->rows);
1554         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555         idx <<= MONO_CUSTOM_ATTR_BITS;
1556         idx |= type;
1557         for (i = 0; i < count; ++i) {
1558                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561                 if (!mono_error_ok (error)) goto fail;
1562                 type = mono_metadata_token_index (token);
1563                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564                 switch (mono_metadata_token_table (token)) {
1565                 case MONO_TABLE_METHOD:
1566                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1567                         /*
1568                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569                          * method, not the one returned by mono_image_create_token ().
1570                          */
1571                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1572                         break;
1573                 case MONO_TABLE_MEMBERREF:
1574                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1575                         break;
1576                 default:
1577                         g_warning ("got wrong token in custom attr");
1578                         continue;
1579                 }
1580                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1581                 p = blob_size;
1582                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585                 values += MONO_CUSTOM_ATTR_SIZE;
1586                 ++table->next_idx;
1587         }
1588
1589         return TRUE;
1590
1591 fail:
1592         return FALSE;
1593 }
1594
1595 static void
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1597 {
1598         MONO_REQ_GC_UNSAFE_MODE;
1599
1600         MonoDynamicTable *table;
1601         guint32 *values;
1602         guint32 count, i, idx;
1603         MonoReflectionPermissionSet *perm;
1604
1605         if (!permissions)
1606                 return;
1607
1608         count = mono_array_length (permissions);
1609         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610         table->rows += count;
1611         alloc_table (table, table->rows);
1612
1613         for (i = 0; i < mono_array_length (permissions); ++i) {
1614                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1615
1616                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1617
1618                 idx = mono_metadata_token_index (parent_token);
1619                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620                 switch (mono_metadata_token_table (parent_token)) {
1621                 case MONO_TABLE_TYPEDEF:
1622                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1623                         break;
1624                 case MONO_TABLE_METHOD:
1625                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1626                         break;
1627                 case MONO_TABLE_ASSEMBLY:
1628                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1629                         break;
1630                 default:
1631                         g_assert_not_reached ();
1632                 }
1633
1634                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635                 values [MONO_DECL_SECURITY_PARENT] = idx;
1636                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1637
1638                 ++table->next_idx;
1639         }
1640 }
1641
1642 /*
1643  * Fill in the MethodDef and ParamDef tables for a method.
1644  * This is used for both normal methods and constructors.
1645  */
1646 static gboolean
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1648 {
1649         MONO_REQ_GC_UNSAFE_MODE;
1650
1651         MonoDynamicTable *table;
1652         guint32 *values;
1653         guint i, count;
1654
1655         mono_error_init (error);
1656
1657         /* room in this table is already allocated */
1658         table = &assembly->tables [MONO_TABLE_METHOD];
1659         *mb->table_idx = table->next_idx ++;
1660         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663         values [MONO_METHOD_FLAGS] = mb->attrs;
1664         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666         return_val_if_nok (error, FALSE);
1667         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669
1670         table = &assembly->tables [MONO_TABLE_PARAM];
1671         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1672
1673         mono_image_add_decl_security (assembly, 
1674                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1675
1676         if (mb->pinfo) {
1677                 MonoDynamicTable *mtable;
1678                 guint32 *mvalues;
1679                 
1680                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1682                 
1683                 count = 0;
1684                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685                         if (mono_array_get (mb->pinfo, gpointer, i))
1686                                 count++;
1687                 }
1688                 table->rows += count;
1689                 alloc_table (table, table->rows);
1690                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692                         MonoReflectionParamBuilder *pb;
1693                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1695                                 values [MONO_PARAM_SEQUENCE] = i;
1696                                 if (pb->name != NULL) {
1697                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1698                                 } else {
1699                                         values [MONO_PARAM_NAME] = 0;
1700                                 }
1701                                 values += MONO_PARAM_SIZE;
1702                                 if (pb->marshal_info) {
1703                                         mtable->rows++;
1704                                         alloc_table (mtable, mtable->rows);
1705                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708                                         return_val_if_nok (error, FALSE);
1709                                 }
1710                                 pb->table_idx = table->next_idx++;
1711                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712                                         guint32 field_type = 0;
1713                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1714                                         mtable->rows ++;
1715                                         alloc_table (mtable, mtable->rows);
1716                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1720                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1721                                 }
1722                         }
1723                 }
1724         }
1725
1726         return TRUE;
1727 }
1728
1729 #ifndef DISABLE_REFLECTION_EMIT
1730 static gboolean
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1732 {
1733         MONO_REQ_GC_UNSAFE_MODE;
1734
1735         mono_error_init (error);
1736         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1737
1738         rmb->ilgen = mb->ilgen;
1739         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740         return_val_if_nok (error, FALSE);
1741         rmb->parameters = mb->parameters;
1742         rmb->generic_params = mb->generic_params;
1743         rmb->generic_container = mb->generic_container;
1744         rmb->opt_types = NULL;
1745         rmb->pinfo = mb->pinfo;
1746         rmb->attrs = mb->attrs;
1747         rmb->iattrs = mb->iattrs;
1748         rmb->call_conv = mb->call_conv;
1749         rmb->code = mb->code;
1750         rmb->type = mb->type;
1751         rmb->name = mb->name;
1752         rmb->table_idx = &mb->table_idx;
1753         rmb->init_locals = mb->init_locals;
1754         rmb->skip_visibility = FALSE;
1755         rmb->return_modreq = mb->return_modreq;
1756         rmb->return_modopt = mb->return_modopt;
1757         rmb->param_modreq = mb->param_modreq;
1758         rmb->param_modopt = mb->param_modopt;
1759         rmb->permissions = mb->permissions;
1760         rmb->mhandle = mb->mhandle;
1761         rmb->nrefs = 0;
1762         rmb->refs = NULL;
1763
1764         if (mb->dll) {
1765                 rmb->charset = mb->charset;
1766                 rmb->extra_flags = mb->extra_flags;
1767                 rmb->native_cc = mb->native_cc;
1768                 rmb->dllentry = mb->dllentry;
1769                 rmb->dll = mb->dll;
1770         }
1771
1772         return TRUE;
1773 }
1774
1775 static gboolean
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1777 {
1778         MONO_REQ_GC_UNSAFE_MODE;
1779
1780         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1781
1782         mono_error_init (error);
1783
1784         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1785
1786         rmb->ilgen = mb->ilgen;
1787         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788         return_val_if_nok (error, FALSE);
1789         rmb->parameters = mb->parameters;
1790         rmb->generic_params = NULL;
1791         rmb->generic_container = NULL;
1792         rmb->opt_types = NULL;
1793         rmb->pinfo = mb->pinfo;
1794         rmb->attrs = mb->attrs;
1795         rmb->iattrs = mb->iattrs;
1796         rmb->call_conv = mb->call_conv;
1797         rmb->code = NULL;
1798         rmb->type = mb->type;
1799         rmb->name = mono_string_new (mono_domain_get (), name);
1800         rmb->table_idx = &mb->table_idx;
1801         rmb->init_locals = mb->init_locals;
1802         rmb->skip_visibility = FALSE;
1803         rmb->return_modreq = NULL;
1804         rmb->return_modopt = NULL;
1805         rmb->param_modreq = mb->param_modreq;
1806         rmb->param_modopt = mb->param_modopt;
1807         rmb->permissions = mb->permissions;
1808         rmb->mhandle = mb->mhandle;
1809         rmb->nrefs = 0;
1810         rmb->refs = NULL;
1811
1812         return TRUE;
1813 }
1814
1815 static void
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1817 {
1818         MONO_REQ_GC_UNSAFE_MODE;
1819
1820         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1821
1822         rmb->ilgen = mb->ilgen;
1823         rmb->rtype = mb->rtype;
1824         rmb->parameters = mb->parameters;
1825         rmb->generic_params = NULL;
1826         rmb->generic_container = NULL;
1827         rmb->opt_types = NULL;
1828         rmb->pinfo = NULL;
1829         rmb->attrs = mb->attrs;
1830         rmb->iattrs = 0;
1831         rmb->call_conv = mb->call_conv;
1832         rmb->code = NULL;
1833         rmb->type = (MonoObject *) mb->owner;
1834         rmb->name = mb->name;
1835         rmb->table_idx = NULL;
1836         rmb->init_locals = mb->init_locals;
1837         rmb->skip_visibility = mb->skip_visibility;
1838         rmb->return_modreq = NULL;
1839         rmb->return_modopt = NULL;
1840         rmb->param_modreq = NULL;
1841         rmb->param_modopt = NULL;
1842         rmb->permissions = NULL;
1843         rmb->mhandle = mb->mhandle;
1844         rmb->nrefs = 0;
1845         rmb->refs = NULL;
1846 }       
1847 #endif
1848
1849 static gboolean
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1851 {
1852         MONO_REQ_GC_UNSAFE_MODE;
1853
1854         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855         MonoDynamicTable *table;
1856         guint32 *values;
1857         guint32 tok;
1858         MonoReflectionMethod *m;
1859         int i;
1860
1861         mono_error_init (error);
1862
1863         if (!mb->override_methods)
1864                 return TRUE;
1865
1866         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1868
1869                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1870                 table->rows ++;
1871                 alloc_table (table, table->rows);
1872                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1875
1876                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877                 return_val_if_nok (error, FALSE);
1878
1879                 switch (mono_metadata_token_table (tok)) {
1880                 case MONO_TABLE_MEMBERREF:
1881                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1882                         break;
1883                 case MONO_TABLE_METHOD:
1884                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1885                         break;
1886                 default:
1887                         g_assert_not_reached ();
1888                 }
1889                 values [MONO_METHODIMPL_DECLARATION] = tok;
1890         }
1891
1892         return TRUE;
1893 }
1894
1895 #ifndef DISABLE_REFLECTION_EMIT
1896 static gboolean
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1898 {
1899         MONO_REQ_GC_UNSAFE_MODE;
1900
1901         MonoDynamicTable *table;
1902         guint32 *values;
1903         ReflectionMethodBuilder rmb;
1904         int i;
1905
1906         mono_error_init (error);
1907
1908         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909             !mono_image_basic_method (&rmb, assembly, error))
1910                 return FALSE;
1911
1912         mb->table_idx = *rmb.table_idx;
1913
1914         if (mb->dll) { /* It's a P/Invoke method */
1915                 guint32 moduleref;
1916                 /* map CharSet values to on-disk values */
1917                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918                 int extra_flags = mb->extra_flags;
1919                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1920                 table->rows ++;
1921                 alloc_table (table, table->rows);
1922                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1923                 
1924                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1926                 if (mb->dllentry)
1927                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1928                 else
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1933                         table->rows ++;
1934                         alloc_table (table, table->rows);
1935                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1937                 }
1938         }
1939
1940         if (mb->generic_params) {
1941                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942                 table->rows += mono_array_length (mb->generic_params);
1943                 alloc_table (table, table->rows);
1944                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1946
1947                         mono_image_get_generic_param_info (
1948                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1949                 }
1950         }
1951
1952         return TRUE;
1953 }
1954
1955 static gboolean
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1957 {
1958         MONO_REQ_GC_UNSAFE_MODE;
1959
1960         ReflectionMethodBuilder rmb;
1961
1962         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1963                 return FALSE;
1964
1965         if (!mono_image_basic_method (&rmb, assembly, error))
1966                 return FALSE;
1967
1968         mb->table_idx = *rmb.table_idx;
1969
1970         return TRUE;
1971 }
1972 #endif
1973
1974 static char*
1975 type_get_fully_qualified_name (MonoType *type)
1976 {
1977         MONO_REQ_GC_NEUTRAL_MODE;
1978
1979         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1980 }
1981
1982 static char*
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1984 {
1985         MONO_REQ_GC_UNSAFE_MODE;
1986
1987         MonoClass *klass;
1988         MonoAssembly *ta;
1989
1990         klass = mono_class_from_mono_type (type);
1991         if (!klass) 
1992                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993         ta = klass->image->assembly;
1994         if (assembly_is_dynamic (ta) || (ta == ass)) {
1995                 if (klass->generic_class || klass->generic_container)
1996                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1998                 else
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2000         }
2001
2002         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2003 }
2004
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2007 static guint32
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2009 {
2010         MONO_REQ_GC_NEUTRAL_MODE;
2011
2012         SigBuffer buf;
2013         guint32 idx, i, token;
2014
2015         if (!assembly->save)
2016                 return 0;
2017
2018         sigbuffer_init (&buf, 32);
2019         
2020         sigbuffer_add_value (&buf, 0x06);
2021         /* encode custom attributes before the type */
2022         if (type->num_mods) {
2023                 for (i = 0; i < type->num_mods; ++i) {
2024                         if (field_image) {
2025                                 MonoError error;
2026                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2028
2029                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2030                         } else {
2031                                 token = type->modifiers [i].token;
2032                         }
2033
2034                         if (type->modifiers [i].required)
2035                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2036                         else
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2038
2039                         sigbuffer_add_value (&buf, token);
2040                 }
2041         }
2042         encode_type (assembly, type, &buf);
2043         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044         sigbuffer_free (&buf);
2045         return idx;
2046 }
2047 #endif
2048
2049 static guint32
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2051 {
2052         MONO_REQ_GC_UNSAFE_MODE;
2053
2054         mono_error_init (error);
2055
2056         SigBuffer buf;
2057         guint32 idx;
2058         guint32 typespec = 0;
2059         MonoType *type;
2060         MonoClass *klass;
2061
2062         init_type_builder_generics (fb->type);
2063
2064         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065         return_val_if_nok (error, 0);
2066         klass = mono_class_from_mono_type (type);
2067
2068         sigbuffer_init (&buf, 32);
2069         
2070         sigbuffer_add_value (&buf, 0x06);
2071         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2072         if (!is_ok (error))
2073                 goto fail;
2074         /* encode custom attributes before the type */
2075
2076         if (klass->generic_container)
2077                 typespec = create_typespec (assembly, type);
2078
2079         if (typespec) {
2080                 MonoGenericClass *gclass;
2081                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082                 encode_generic_class (assembly, gclass, &buf);
2083         } else {
2084                 encode_type (assembly, type, &buf);
2085         }
2086         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087         sigbuffer_free (&buf);
2088         return idx;
2089 fail:
2090         sigbuffer_free (&buf);
2091         return 0;
2092 }
2093
2094 static guint32
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2096 {
2097         MONO_REQ_GC_UNSAFE_MODE;
2098
2099         char blob_size [64];
2100         char *b = blob_size;
2101         char *box_val;
2102         char* buf;
2103         guint32 idx = 0, len = 0, dummy = 0;
2104
2105         buf = (char *)g_malloc (64);
2106         if (!val) {
2107                 *ret_type = MONO_TYPE_CLASS;
2108                 len = 4;
2109                 box_val = (char*)&dummy;
2110         } else {
2111                 box_val = ((char*)val) + sizeof (MonoObject);
2112                 *ret_type = val->vtable->klass->byval_arg.type;
2113         }
2114 handle_enum:
2115         switch (*ret_type) {
2116         case MONO_TYPE_BOOLEAN:
2117         case MONO_TYPE_U1:
2118         case MONO_TYPE_I1:
2119                 len = 1;
2120                 break;
2121         case MONO_TYPE_CHAR:
2122         case MONO_TYPE_U2:
2123         case MONO_TYPE_I2:
2124                 len = 2;
2125                 break;
2126         case MONO_TYPE_U4:
2127         case MONO_TYPE_I4:
2128         case MONO_TYPE_R4:
2129                 len = 4;
2130                 break;
2131         case MONO_TYPE_U8:
2132         case MONO_TYPE_I8:
2133                 len = 8;
2134                 break;
2135         case MONO_TYPE_R8:
2136                 len = 8;
2137                 break;
2138         case MONO_TYPE_VALUETYPE: {
2139                 MonoClass *klass = val->vtable->klass;
2140                 
2141                 if (klass->enumtype) {
2142                         *ret_type = mono_class_enum_basetype (klass)->type;
2143                         goto handle_enum;
2144                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2145                         len = 8;
2146                 } else 
2147                         g_error ("we can't encode valuetypes, we should have never reached this line");
2148                 break;
2149         }
2150         case MONO_TYPE_CLASS:
2151                 break;
2152         case MONO_TYPE_STRING: {
2153                 MonoString *str = (MonoString*)val;
2154                 /* there is no signature */
2155                 len = str->length * 2;
2156                 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2158                 {
2159                         char *swapped = g_malloc (2 * mono_string_length (str));
2160                         const char *p = (const char*)mono_string_chars (str);
2161
2162                         swap_with_size (swapped, p, 2, mono_string_length (str));
2163                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2164                         g_free (swapped);
2165                 }
2166 #else
2167                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2168 #endif
2169
2170                 g_free (buf);
2171                 return idx;
2172         }
2173         case MONO_TYPE_GENERICINST:
2174                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2175                 goto handle_enum;
2176         default:
2177                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2178         }
2179
2180         /* there is no signature */
2181         mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184         swap_with_size (blob_size, box_val, len, 1);
2185         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2186 #else
2187         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2188 #endif
2189
2190         g_free (buf);
2191         return idx;
2192 }
2193
2194 static guint32
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2196 {
2197         MONO_REQ_GC_UNSAFE_MODE;
2198
2199         mono_error_init (error);
2200
2201         char *str;
2202         SigBuffer buf;
2203         guint32 idx, len;
2204
2205         sigbuffer_init (&buf, 32);
2206
2207         sigbuffer_add_value (&buf, minfo->type);
2208
2209         switch (minfo->type) {
2210         case MONO_NATIVE_BYVALTSTR:
2211         case MONO_NATIVE_BYVALARRAY:
2212                 sigbuffer_add_value (&buf, minfo->count);
2213                 break;
2214         case MONO_NATIVE_LPARRAY:
2215                 if (minfo->eltype || minfo->has_size) {
2216                         sigbuffer_add_value (&buf, minfo->eltype);
2217                         if (minfo->has_size) {
2218                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2220
2221                                 /* LAMESPEC: ElemMult is undocumented */
2222                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2223                         }
2224                 }
2225                 break;
2226         case MONO_NATIVE_SAFEARRAY:
2227                 if (minfo->eltype)
2228                         sigbuffer_add_value (&buf, minfo->eltype);
2229                 break;
2230         case MONO_NATIVE_CUSTOM:
2231                 if (minfo->guid) {
2232                         str = mono_string_to_utf8 (minfo->guid);
2233                         len = strlen (str);
2234                         sigbuffer_add_value (&buf, len);
2235                         sigbuffer_add_mem (&buf, str, len);
2236                         g_free (str);
2237                 } else {
2238                         sigbuffer_add_value (&buf, 0);
2239                 }
2240                 /* native type name */
2241                 sigbuffer_add_value (&buf, 0);
2242                 /* custom marshaler type name */
2243                 if (minfo->marshaltype || minfo->marshaltyperef) {
2244                         if (minfo->marshaltyperef) {
2245                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246                                 if (!is_ok (error)) {
2247                                         sigbuffer_free (&buf);
2248                                         return 0;
2249                                 }
2250                                 str = type_get_fully_qualified_name (marshaltype);
2251                         } else
2252                                 str = mono_string_to_utf8 (minfo->marshaltype);
2253                         len = strlen (str);
2254                         sigbuffer_add_value (&buf, len);
2255                         sigbuffer_add_mem (&buf, str, len);
2256                         g_free (str);
2257                 } else {
2258                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 if (minfo->mcookie) {
2262                         str = mono_string_to_utf8 (minfo->mcookie);
2263                         len = strlen (str);
2264                         sigbuffer_add_value (&buf, len);
2265                         sigbuffer_add_mem (&buf, str, len);
2266                         g_free (str);
2267                 } else {
2268                         sigbuffer_add_value (&buf, 0);
2269                 }
2270                 break;
2271         default:
2272                 break;
2273         }
2274         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275         sigbuffer_free (&buf);
2276         return idx;
2277 }
2278
2279 static void
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2281 {
2282         MONO_REQ_GC_UNSAFE_MODE;
2283
2284         mono_error_init (error);
2285
2286         MonoDynamicTable *table;
2287         guint32 *values;
2288
2289         /* maybe this fixup should be done in the C# code */
2290         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292         table = &assembly->tables [MONO_TABLE_FIELD];
2293         fb->table_idx = table->next_idx ++;
2294         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297         values [MONO_FIELD_FLAGS] = fb->attrs;
2298         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299         return_if_nok (error);
2300
2301
2302         if (fb->offset != -1) {
2303                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2304                 table->rows ++;
2305                 alloc_table (table, table->rows);
2306                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2309         }
2310         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2313                 table->rows ++;
2314                 alloc_table (table, table->rows);
2315                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318                 values [MONO_CONSTANT_TYPE] = field_type;
2319                 values [MONO_CONSTANT_PADDING] = 0;
2320         }
2321         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2322                 guint32 rva_idx;
2323                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2324                 table->rows ++;
2325                 alloc_table (table, table->rows);
2326                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2328                 /*
2329                  * We store it in the code section because it's simpler for now.
2330                  */
2331                 if (fb->rva_data) {
2332                         if (mono_array_length (fb->rva_data) >= 10)
2333                                 stream_data_align (&assembly->code);
2334                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2335                 } else
2336                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2338         }
2339         if (fb->marshal_info) {
2340                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2341                 table->rows ++;
2342                 alloc_table (table, table->rows);
2343                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346                 return_if_nok (error);
2347         }
2348 }
2349
2350 static guint32
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2352 {
2353         MONO_REQ_GC_UNSAFE_MODE;
2354
2355         mono_error_init (error);
2356
2357         SigBuffer buf;
2358         guint32 nparams = 0;
2359         MonoReflectionMethodBuilder *mb = fb->get_method;
2360         MonoReflectionMethodBuilder *smb = fb->set_method;
2361         guint32 idx, i;
2362
2363         if (mb && mb->parameters)
2364                 nparams = mono_array_length (mb->parameters);
2365         if (!mb && smb && smb->parameters)
2366                 nparams = mono_array_length (smb->parameters) - 1;
2367         sigbuffer_init (&buf, 32);
2368         if (fb->call_conv & 0x20)
2369                 sigbuffer_add_byte (&buf, 0x28);
2370         else
2371                 sigbuffer_add_byte (&buf, 0x08);
2372         sigbuffer_add_value (&buf, nparams);
2373         if (mb) {
2374                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2375                 if (!is_ok (error))
2376                         goto fail;
2377                 for (i = 0; i < nparams; ++i) {
2378                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379                         encode_reflection_type (assembly, pt, &buf, error);
2380                         if (!is_ok (error))
2381                                 goto fail;
2382                 }
2383         } else if (smb && smb->parameters) {
2384                 /* the property type is the last param */
2385                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2386                 if (!is_ok (error))
2387                         goto fail;
2388
2389                 for (i = 0; i < nparams; ++i) {
2390                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391                         encode_reflection_type (assembly, pt, &buf, error);
2392                         if (!is_ok (error))
2393                                 goto fail;
2394                 }
2395         } else {
2396                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2397                 if (!is_ok (error))
2398                         goto fail;
2399         }
2400
2401         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402         sigbuffer_free (&buf);
2403         return idx;
2404 fail:
2405         sigbuffer_free (&buf);
2406         return 0;
2407 }
2408
2409 static void
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         mono_error_init (error);
2415
2416         MonoDynamicTable *table;
2417         guint32 *values;
2418         guint num_methods = 0;
2419         guint32 semaidx;
2420
2421         /* 
2422          * we need to set things in the following tables:
2423          * PROPERTYMAP (info already filled in _get_type_info ())
2424          * PROPERTY    (rows already preallocated in _get_type_info ())
2425          * METHOD      (method info already done with the generic method code)
2426          * METHODSEMANTICS
2427          * CONSTANT
2428          */
2429         table = &assembly->tables [MONO_TABLE_PROPERTY];
2430         pb->table_idx = table->next_idx ++;
2431         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435         return_if_nok (error);
2436
2437
2438         /* FIXME: we still don't handle 'other' methods */
2439         if (pb->get_method) num_methods ++;
2440         if (pb->set_method) num_methods ++;
2441
2442         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443         table->rows += num_methods;
2444         alloc_table (table, table->rows);
2445
2446         if (pb->get_method) {
2447                 semaidx = table->next_idx ++;
2448                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2452         }
2453         if (pb->set_method) {
2454                 semaidx = table->next_idx ++;
2455                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2459         }
2460         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2463                 table->rows ++;
2464                 alloc_table (table, table->rows);
2465                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468                 values [MONO_CONSTANT_TYPE] = field_type;
2469                 values [MONO_CONSTANT_PADDING] = 0;
2470         }
2471 }
2472
2473 static void
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2475 {
2476         MONO_REQ_GC_UNSAFE_MODE;
2477
2478         MonoDynamicTable *table;
2479         guint32 *values;
2480         guint num_methods = 0;
2481         guint32 semaidx;
2482
2483         /* 
2484          * we need to set things in the following tables:
2485          * EVENTMAP (info already filled in _get_type_info ())
2486          * EVENT    (rows already preallocated in _get_type_info ())
2487          * METHOD      (method info already done with the generic method code)
2488          * METHODSEMANTICS
2489          */
2490         table = &assembly->tables [MONO_TABLE_EVENT];
2491         eb->table_idx = table->next_idx ++;
2492         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494         values [MONO_EVENT_FLAGS] = eb->attrs;
2495         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496         return_if_nok (error);
2497         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2498
2499         /*
2500          * FIXME: we still don't handle 'other' methods 
2501          */
2502         if (eb->add_method) num_methods ++;
2503         if (eb->remove_method) num_methods ++;
2504         if (eb->raise_method) num_methods ++;
2505
2506         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507         table->rows += num_methods;
2508         alloc_table (table, table->rows);
2509
2510         if (eb->add_method) {
2511                 semaidx = table->next_idx ++;
2512                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2516         }
2517         if (eb->remove_method) {
2518                 semaidx = table->next_idx ++;
2519                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2523         }
2524         if (eb->raise_method) {
2525                 semaidx = table->next_idx ++;
2526                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2530         }
2531 }
2532
2533 static void
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2535 {
2536         MONO_REQ_GC_UNSAFE_MODE;
2537
2538         mono_error_init (error);
2539
2540         MonoDynamicTable *table;
2541         guint32 num_constraints, i;
2542         guint32 *values;
2543         guint32 table_idx;
2544
2545         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546         num_constraints = gparam->iface_constraints ?
2547                 mono_array_length (gparam->iface_constraints) : 0;
2548         table->rows += num_constraints;
2549         if (gparam->base_type)
2550                 table->rows++;
2551         alloc_table (table, table->rows);
2552
2553         if (gparam->base_type) {
2554                 table_idx = table->next_idx ++;
2555                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2556
2557                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2558                 return_if_nok (error);
2559                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2561         }
2562
2563         for (i = 0; i < num_constraints; i++) {
2564                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565                         gparam->iface_constraints, gpointer, i);
2566
2567                 table_idx = table->next_idx ++;
2568                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2569
2570                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2571                 return_if_nok (error);
2572
2573                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2575         }
2576 }
2577
2578 static void
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2580 {
2581         MONO_REQ_GC_UNSAFE_MODE;
2582
2583         GenericParamTableEntry *entry;
2584
2585         /*
2586          * The GenericParam table must be sorted according to the `owner' field.
2587          * We need to do this sorting prior to writing the GenericParamConstraint
2588          * table, since we have to use the final GenericParam table indices there
2589          * and they must also be sorted.
2590          */
2591
2592         entry = g_new0 (GenericParamTableEntry, 1);
2593         entry->owner = owner;
2594         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596         entry->gparam = gparam;
2597         
2598         g_ptr_array_add (assembly->gen_params, entry);
2599 }
2600
2601 static gboolean
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2603 {
2604         MONO_REQ_GC_UNSAFE_MODE;
2605
2606         MonoDynamicTable *table;
2607         MonoGenericParam *param;
2608         guint32 *values;
2609         guint32 table_idx;
2610
2611         mono_error_init (error);
2612
2613         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614         table_idx = table->next_idx ++;
2615         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2616
2617         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618         return_val_if_nok (error, FALSE);
2619
2620         param = gparam_type->data.generic_param;
2621
2622         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2626
2627         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2628                 return FALSE;
2629
2630         encode_constraints (entry->gparam, table_idx, assembly, error);
2631         return_val_if_nok (error, FALSE);
2632
2633         return TRUE;
2634 }
2635
2636 static guint32
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2638 {
2639         MONO_REQ_GC_UNSAFE_MODE;
2640
2641         MonoDynamicTable *table;
2642         guint32 token;
2643         guint32 *values;
2644         guint32 cols [MONO_ASSEMBLY_SIZE];
2645         const char *pubkey;
2646         guint32 publen;
2647
2648         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2649                 return token;
2650
2651         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653                 token = table->next_idx ++;
2654                 table->rows ++;
2655                 alloc_table (table, table->rows);
2656                 values = table->values + token * MONO_MODULEREF_SIZE;
2657                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2658
2659                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2662
2663                 return token;
2664         }
2665         
2666         if (assembly_is_dynamic (image->assembly))
2667                 /* FIXME: */
2668                 memset (cols, 0, sizeof (cols));
2669         else {
2670                 /* image->assembly->image is the manifest module */
2671                 image = image->assembly->image;
2672                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2673         }
2674
2675         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676         token = table->next_idx ++;
2677         table->rows ++;
2678         alloc_table (table, table->rows);
2679         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2688
2689         if (strcmp ("", image->assembly->aname.culture)) {
2690                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691                                 image->assembly->aname.culture);
2692         }
2693
2694         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695                 guchar pubtoken [9];
2696                 pubtoken [0] = 8;
2697                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699         } else {
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2701         }
2702         token <<= MONO_RESOLUTION_SCOPE_BITS;
2703         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2705         return token;
2706 }
2707
2708 static guint32
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2710 {
2711         MONO_REQ_GC_NEUTRAL_MODE;
2712
2713         MonoDynamicTable *table;
2714         guint32 *values;
2715         guint32 token;
2716         SigBuffer buf;
2717
2718         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2719                 return token;
2720
2721         sigbuffer_init (&buf, 32);
2722         switch (type->type) {
2723         case MONO_TYPE_FNPTR:
2724         case MONO_TYPE_PTR:
2725         case MONO_TYPE_SZARRAY:
2726         case MONO_TYPE_ARRAY:
2727         case MONO_TYPE_VAR:
2728         case MONO_TYPE_MVAR:
2729         case MONO_TYPE_GENERICINST:
2730                 encode_type (assembly, type, &buf);
2731                 break;
2732         case MONO_TYPE_CLASS:
2733         case MONO_TYPE_VALUETYPE: {
2734                 MonoClass *k = mono_class_from_mono_type (type);
2735                 if (!k || !k->generic_container) {
2736                         sigbuffer_free (&buf);
2737                         return 0;
2738                 }
2739                 encode_type (assembly, type, &buf);
2740                 break;
2741         }
2742         default:
2743                 sigbuffer_free (&buf);
2744                 return 0;
2745         }
2746
2747         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748         if (assembly->save) {
2749                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750                 alloc_table (table, table->rows + 1);
2751                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752                 values [MONO_TYPESPEC_SIGNATURE] = token;
2753         }
2754         sigbuffer_free (&buf);
2755
2756         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2758         table->next_idx ++;
2759         return token;
2760 }
2761
2762 static guint32
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2764 {
2765         MONO_REQ_GC_UNSAFE_MODE;
2766
2767         MonoDynamicTable *table;
2768         guint32 *values;
2769         guint32 token, scope, enclosing;
2770         MonoClass *klass;
2771
2772         /* if the type requires a typespec, we must try that first*/
2773         if (try_typespec && (token = create_typespec (assembly, type)))
2774                 return token;
2775         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2776         if (token)
2777                 return token;
2778         klass = mono_class_from_mono_type (type);
2779         if (!klass)
2780                 klass = mono_class_from_mono_type (type);
2781
2782         /*
2783          * If it's in the same module and not a generic type parameter:
2784          */
2785         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2786                         (type->type != MONO_TYPE_MVAR)) {
2787                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2790                 return token;
2791         }
2792
2793         if (klass->nested_in) {
2794                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795                 /* get the typeref idx of the enclosing type */
2796                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798         } else {
2799                 scope = resolution_scope_from_image (assembly, klass->image);
2800         }
2801         table = &assembly->tables [MONO_TABLE_TYPEREF];
2802         if (assembly->save) {
2803                 alloc_table (table, table->rows + 1);
2804                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805                 values [MONO_TYPEREF_SCOPE] = scope;
2806                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2808         }
2809         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811         table->next_idx ++;
2812         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2813         return token;
2814 }
2815
2816 /*
2817  * Despite the name, we handle also TypeSpec (with the above helper).
2818  */
2819 static guint32
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2821 {
2822         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2823 }
2824
2825 #ifndef DISABLE_REFLECTION_EMIT
2826 static guint32
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2828 {
2829         MONO_REQ_GC_NEUTRAL_MODE;
2830
2831         MonoDynamicTable *table;
2832         guint32 *values;
2833         guint32 token, pclass;
2834
2835         switch (parent & MONO_TYPEDEFORREF_MASK) {
2836         case MONO_TYPEDEFORREF_TYPEREF:
2837                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838                 break;
2839         case MONO_TYPEDEFORREF_TYPESPEC:
2840                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841                 break;
2842         case MONO_TYPEDEFORREF_TYPEDEF:
2843                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2844                 break;
2845         default:
2846                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2847                 return 0;
2848         }
2849         /* extract the index */
2850         parent >>= MONO_TYPEDEFORREF_BITS;
2851
2852         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2853
2854         if (assembly->save) {
2855                 alloc_table (table, table->rows + 1);
2856                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2860         }
2861
2862         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2863         table->next_idx ++;
2864
2865         return token;
2866 }
2867
2868 /*
2869  * Insert a memberef row into the metadata: the token that point to the memberref
2870  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871  * mono_image_get_fieldref_token()).
2872  * The sig param is an index to an already built signature.
2873  */
2874 static guint32
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2876 {
2877         MONO_REQ_GC_NEUTRAL_MODE;
2878
2879         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880         return mono_image_add_memberef_row (assembly, parent, name, sig);
2881 }
2882
2883
2884 static guint32
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2886 {
2887         MONO_REQ_GC_NEUTRAL_MODE;
2888
2889         guint32 token;
2890         MonoMethodSignature *sig;
2891         
2892         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2893
2894         if (create_typespec) {
2895                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2896                 if (token)
2897                         return token;
2898         } 
2899
2900         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901         if (token && !create_typespec)
2902                 return token;
2903
2904         g_assert (!method->is_inflated);
2905         if (!token) {
2906                 /*
2907                  * A methodref signature can't contain an unmanaged calling convention.
2908                  */
2909                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911                         sig->call_convention = MONO_CALL_DEFAULT;
2912                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913                         method->name,  method_encode_signature (assembly, sig));
2914                 g_free (sig);
2915                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2916         }
2917
2918         if (create_typespec) {
2919                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922
2923                 if (assembly->save) {
2924                         guint32 *values;
2925
2926                         alloc_table (table, table->rows + 1);
2927                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928                         values [MONO_METHODSPEC_METHOD] = token;
2929                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2930                 }
2931
2932                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933                 table->next_idx ++;
2934                 /*methodspec and memberef tokens are diferent, */
2935                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2936                 return token;
2937         }
2938         return token;
2939 }
2940
2941 static guint32
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2943 {
2944         guint32 token, parent, sig;
2945         ReflectionMethodBuilder rmb;
2946         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2947         
2948         mono_error_init (error);
2949         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2950         if (token)
2951                 return token;
2952
2953         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2954                 return 0;
2955
2956         /*
2957          * A methodref signature can't contain an unmanaged calling convention.
2958          * Since some flags are encoded as part of call_conv, we need to check against it.
2959         */
2960         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2962
2963         sig = method_builder_encode_signature (assembly, &rmb, error);
2964         return_val_if_nok (error, 0);
2965
2966         if (tb->generic_params) {
2967                 parent = create_generic_typespec (assembly, tb, error);
2968                 return_val_if_nok (error, 0);
2969         } else {
2970                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971                 return_val_if_nok (error, 0);
2972
2973                 parent = mono_image_typedef_or_ref (assembly, t);
2974         }
2975
2976         char *name = mono_string_to_utf8 (method->name);
2977
2978         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979         g_free (name);
2980
2981         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2982
2983         return token;
2984 }
2985
2986 static guint32
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988                                      const gchar *name, guint32 sig)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 token;
2992         guint32 *values;
2993         
2994         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2995
2996         if (assembly->save) {
2997                 alloc_table (table, table->rows + 1);
2998                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999                 values [MONO_MEMBERREF_CLASS] = original;
3000                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3012 {
3013         SigBuffer buf;
3014         int i;
3015         guint32 nparams = mono_array_length (mb->generic_params);
3016         guint32 idx;
3017
3018         if (!assembly->save)
3019                 return 0;
3020
3021         sigbuffer_init (&buf, 32);
3022
3023         sigbuffer_add_value (&buf, 0xa);
3024         sigbuffer_add_value (&buf, nparams);
3025
3026         for (i = 0; i < nparams; i++) {
3027                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028                 sigbuffer_add_value (&buf, i);
3029         }
3030
3031         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032         sigbuffer_free (&buf);
3033         return idx;
3034 }
3035
3036 static guint32
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3038 {
3039         MonoDynamicTable *table;
3040         guint32 *values;
3041         guint32 token, mtoken = 0;
3042
3043         mono_error_init (error);
3044         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3045         if (token)
3046                 return token;
3047
3048         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3049
3050         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051         if (!mono_error_ok (error))
3052                 return 0;
3053
3054         switch (mono_metadata_token_table (mtoken)) {
3055         case MONO_TABLE_MEMBERREF:
3056                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057                 break;
3058         case MONO_TABLE_METHOD:
3059                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060                 break;
3061         default:
3062                 g_assert_not_reached ();
3063         }
3064
3065         if (assembly->save) {
3066                 alloc_table (table, table->rows + 1);
3067                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068                 values [MONO_METHODSPEC_METHOD] = mtoken;
3069                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3070         }
3071
3072         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073         table->next_idx ++;
3074
3075         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3076         return token;
3077 }
3078
3079 static guint32
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3081 {
3082         guint32 token;
3083
3084         mono_error_init (error);
3085
3086         if (mb->generic_params && create_methodspec) 
3087                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3088
3089         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3090         if (token)
3091                 return token;
3092
3093         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094         if (!mono_error_ok (error))
3095                 return 0;
3096         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3097         return token;
3098 }
3099
3100 static guint32
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3102 {
3103         guint32 token, parent, sig;
3104         ReflectionMethodBuilder rmb;
3105         char *name;
3106         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3107         
3108         mono_error_init (error);
3109         
3110         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3111         if (token)
3112                 return token;
3113
3114         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115                 return 0;
3116
3117         if (tb->generic_params) {
3118                 parent = create_generic_typespec (assembly, tb, error);
3119                 return_val_if_nok (error, 0);
3120         } else {
3121                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122                 return_val_if_nok (error, 0);
3123                 parent = mono_image_typedef_or_ref (assembly, type);
3124         }
3125         
3126         name = mono_string_to_utf8 (rmb.name);
3127         sig = method_builder_encode_signature (assembly, &rmb, error);
3128         return_val_if_nok (error, 0);
3129
3130         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3131
3132         g_free (name);
3133         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3134         return token;
3135 }
3136 #endif
3137
3138 static gboolean
3139 is_field_on_inst (MonoClassField *field)
3140 {
3141         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3142 }
3143
3144 /*
3145  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3146  */
3147 static MonoType*
3148 get_field_on_inst_generic_type (MonoClassField *field)
3149 {
3150         MonoClass *klass, *gtd;
3151         MonoDynamicGenericClass *dgclass;
3152         int field_index;
3153
3154         g_assert (is_field_on_inst (field));
3155
3156         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3157
3158         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159                 field_index = field - dgclass->fields;
3160                 return dgclass->field_generic_types [field_index];              
3161         }
3162
3163         klass = field->parent;
3164         gtd = klass->generic_class->container_class;
3165
3166         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167                 field_index = field - klass->fields;
3168                 return gtd->fields [field_index].type;
3169         }
3170
3171         g_assert_not_reached ();
3172         return 0;
3173 }
3174
3175 #ifndef DISABLE_REFLECTION_EMIT
3176 static guint32
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3178 {
3179         MonoType *type;
3180         guint32 token;
3181
3182         g_assert (field);
3183         g_assert (field->parent);
3184
3185         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186         if (token)
3187                 return token;
3188
3189         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190                 int index = field - field->parent->fields;
3191                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3192         } else {
3193                 if (is_field_on_inst (field))
3194                         type = get_field_on_inst_generic_type (field);
3195                 else
3196                         type = mono_field_get_type (field);
3197         }
3198         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199                                                                                         mono_field_get_name (field),
3200                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3201         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3202         return token;
3203 }
3204
3205 static guint32
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3207 {
3208         guint32 token;
3209         MonoClass *klass;
3210         MonoGenericClass *gclass;
3211         MonoType *type;
3212         char *name;
3213
3214         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215         if (token)
3216                 return token;
3217         if (is_sre_field_builder (mono_object_class (f->fb))) {
3218                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220                 return_val_if_nok (error, 0);
3221                 klass = mono_class_from_mono_type (type);
3222                 gclass = type->data.generic_class;
3223                 g_assert (gclass->is_dynamic);
3224
3225                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226                 return_val_if_nok (error, 0);
3227                 name = mono_string_to_utf8 (fb->name);
3228                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3229                 g_free (name);          
3230         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3231                 guint32 sig;
3232                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3233
3234                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235                 return_val_if_nok (error, 0);
3236                 klass = mono_class_from_mono_type (type);
3237
3238                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3240         } else {
3241                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243         }
3244
3245         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3246         return token;
3247 }
3248
3249 static guint32
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3251 {
3252         guint32 sig, token;
3253         MonoClass *klass;
3254         MonoGenericClass *gclass;
3255         MonoType *type;
3256
3257         mono_error_init (error);
3258
3259         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3260
3261         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3262         if (token)
3263                 return token;
3264
3265         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267                 ReflectionMethodBuilder rmb;
3268                 char *name;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 gclass = type->data.generic_class;
3275                 g_assert (gclass->is_dynamic);
3276
3277                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278                         return 0;
3279
3280                 sig = method_builder_encode_signature (assembly, &rmb, error);
3281                 return_val_if_nok (error, 0);
3282
3283                 name = mono_string_to_utf8 (rmb.name);
3284
3285                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3286                 g_free (name);
3287         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3289
3290                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291                 return_val_if_nok (error, 0);
3292                 klass = mono_class_from_mono_type (type);
3293
3294                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3296         } else {
3297                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3299         }
3300
3301
3302         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3303         return token;
3304 }
3305
3306 static MonoMethod*
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 {
3309         MonoClass *klass;
3310         MonoGenericContext tmp_context;
3311         MonoType **type_argv;
3312         MonoGenericInst *ginst;
3313         MonoMethod *method, *inflated;
3314         int count, i;
3315
3316         mono_error_init (error);
3317
3318         init_type_builder_generics ((MonoObject*)m->inst);
3319
3320         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321         return_val_if_nok (error, NULL);
3322
3323         klass = method->klass;
3324
3325         if (m->method_args == NULL)
3326                 return method;
3327
3328         if (method->is_inflated)
3329                 method = ((MonoMethodInflated *) method)->declaring;
3330
3331         count = mono_array_length (m->method_args);
3332
3333         type_argv = g_new0 (MonoType *, count);
3334         for (i = 0; i < count; i++) {
3335                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337                 return_val_if_nok (error, NULL);
3338         }
3339         ginst = mono_metadata_get_generic_inst (count, type_argv);
3340         g_free (type_argv);
3341
3342         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343         tmp_context.method_inst = ginst;
3344
3345         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346         mono_error_assert_ok (error);
3347         return inflated;
3348 }
3349
3350 static guint32
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3352 {
3353         guint32 sig, token = 0;
3354         MonoType *type;
3355         MonoClass *klass;
3356
3357         mono_error_init (error);
3358
3359         if (m->method_args) {
3360                 MonoMethod *inflated;
3361
3362                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363                 return_val_if_nok (error, 0);
3364
3365                 if (create_methodspec)
3366                         token = mono_image_get_methodspec_token (assembly, inflated);
3367                 else
3368                         token = mono_image_get_inflated_method_token (assembly, inflated);
3369                 return token;
3370         }
3371
3372         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3373         if (token)
3374                 return token;
3375
3376         if (is_sre_method_builder (mono_object_class (m->mb))) {
3377                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378                 MonoGenericClass *gclass;
3379                 ReflectionMethodBuilder rmb;
3380                 char *name;
3381
3382                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383                 return_val_if_nok (error, 0);
3384                 klass = mono_class_from_mono_type (type);
3385                 gclass = type->data.generic_class;
3386                 g_assert (gclass->is_dynamic);
3387
3388                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389                         return 0;
3390
3391                 sig = method_builder_encode_signature (assembly, &rmb, error);
3392                 return_val_if_nok (error, 0);
3393
3394                 name = mono_string_to_utf8 (rmb.name);
3395
3396                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3397                 g_free (name);          
3398         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3400
3401                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402                 return_val_if_nok (error, 0);
3403                 klass = mono_class_from_mono_type (type);
3404
3405                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3407         } else {
3408                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410         }
3411
3412         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3413         return token;
3414 }
3415
3416 static guint32
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3418 {
3419         SigBuffer buf;
3420         int i;
3421         guint32 nparams = context->method_inst->type_argc;
3422         guint32 idx;
3423
3424         if (!assembly->save)
3425                 return 0;
3426
3427         sigbuffer_init (&buf, 32);
3428         /*
3429          * FIXME: vararg, explicit_this, differenc call_conv values...
3430          */
3431         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432         sigbuffer_add_value (&buf, nparams);
3433
3434         for (i = 0; i < nparams; i++)
3435                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3436
3437         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438         sigbuffer_free (&buf);
3439         return idx;
3440 }
3441
3442 static guint32
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3444 {
3445         MonoDynamicTable *table;
3446         guint32 *values;
3447         guint32 token, mtoken = 0, sig;
3448         MonoMethodInflated *imethod;
3449         MonoMethod *declaring;
3450
3451         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3452
3453         g_assert (method->is_inflated);
3454         imethod = (MonoMethodInflated *) method;
3455         declaring = imethod->declaring;
3456
3457         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3459
3460         if (!mono_method_signature (declaring)->generic_param_count)
3461                 return mtoken;
3462
3463         switch (mono_metadata_token_table (mtoken)) {
3464         case MONO_TABLE_MEMBERREF:
3465                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3466                 break;
3467         case MONO_TABLE_METHOD:
3468                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469                 break;
3470         default:
3471                 g_assert_not_reached ();
3472         }
3473
3474         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3475
3476         if (assembly->save) {
3477                 alloc_table (table, table->rows + 1);
3478                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479                 values [MONO_METHODSPEC_METHOD] = mtoken;
3480                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481         }
3482
3483         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3484         table->next_idx ++;
3485
3486         return token;
3487 }
3488
3489 static guint32
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3491 {
3492         MonoMethodInflated *imethod;
3493         guint32 token;
3494         
3495         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3496         if (token)
3497                 return token;
3498
3499         g_assert (method->is_inflated);
3500         imethod = (MonoMethodInflated *) method;
3501
3502         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503                 token = method_encode_methodspec (assembly, method);
3504         } else {
3505                 guint32 sig = method_encode_signature (
3506                         assembly, mono_method_signature (imethod->declaring));
3507                 token = mono_image_get_memberref_token (
3508                         assembly, &method->klass->byval_arg, method->name, sig);
3509         }
3510
3511         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3512         return token;
3513 }
3514
3515 static guint32
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3517 {
3518         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519         guint32 sig, token;
3520
3521         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522         token = mono_image_get_memberref_token (
3523                 assembly, &m->klass->byval_arg, m->name, sig);
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3530 {
3531         MonoDynamicTable *table;
3532         MonoClass *klass;
3533         MonoType *type;
3534         guint32 *values;
3535         guint32 token;
3536         SigBuffer buf;
3537         int count, i;
3538
3539         /*
3540          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542          * Because of this, we must not insert it into the `typeref' hash table.
3543          */
3544         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545         return_val_if_nok (error, 0);
3546         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3547         if (token)
3548                 return token;
3549
3550         sigbuffer_init (&buf, 32);
3551
3552         g_assert (tb->generic_params);
3553         klass = mono_class_from_mono_type (type);
3554
3555         if (tb->generic_container)
3556                 mono_reflection_create_generic_class (tb);
3557
3558         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559         g_assert (klass->generic_container);
3560         sigbuffer_add_value (&buf, klass->byval_arg.type);
3561         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562
3563         count = mono_array_length (tb->generic_params);
3564         sigbuffer_add_value (&buf, count);
3565         for (i = 0; i < count; i++) {
3566                 MonoReflectionGenericParam *gparam;
3567
3568                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3570                 if (!is_ok (error))
3571                         goto fail;
3572
3573                 encode_type (assembly, gparam_type, &buf);
3574         }
3575
3576         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3577
3578         if (assembly->save) {
3579                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580                 alloc_table (table, table->rows + 1);
3581                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582                 values [MONO_TYPESPEC_SIGNATURE] = token;
3583         }
3584         sigbuffer_free (&buf);
3585
3586         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3588         table->next_idx ++;
3589         return token;
3590 fail:
3591         sigbuffer_free (&buf);
3592         return 0;
3593 }
3594
3595 /*
3596  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3597  */
3598 static MonoType*
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3600 {
3601         MonoError error;
3602         int i, count, len, pos;
3603         MonoType *t;
3604
3605         count = 0;
3606         if (modreq)
3607                 count += mono_array_length (modreq);
3608         if (modopt)
3609                 count += mono_array_length (modopt);
3610
3611         if (count == 0)
3612                 return mono_metadata_type_dup (NULL, type);
3613
3614         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3615         t = (MonoType *)g_malloc (len);
3616         memcpy (t, type, MONO_SIZEOF_TYPE);
3617
3618         t->num_mods = count;
3619         pos = 0;
3620         if (modreq) {
3621                 for (i = 0; i < mono_array_length (modreq); ++i) {
3622                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, &error);
3623                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3624                         t->modifiers [pos].required = 1;
3625                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3626                         pos ++;
3627                 }
3628         }
3629         if (modopt) {
3630                 for (i = 0; i < mono_array_length (modopt); ++i) {
3631                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, &error);
3632                         mono_error_raise_exception (&error); /* FIXME don't raise here */
3633                         t->modifiers [pos].required = 0;
3634                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3635                         pos ++;
3636                 }
3637         }
3638
3639         return t;
3640 }
3641
3642 static void
3643 init_type_builder_generics (MonoObject *type)
3644 {
3645         MonoReflectionTypeBuilder *tb;
3646
3647         if (!is_sre_type_builder(mono_object_class (type)))
3648                 return;
3649         tb = (MonoReflectionTypeBuilder *)type;
3650
3651         if (tb && tb->generic_container)
3652                 mono_reflection_create_generic_class (tb);
3653 }
3654
3655 static guint32
3656 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3657 {
3658         MonoError error;
3659         MonoDynamicTable *table;
3660         MonoType *custom = NULL, *type;
3661         guint32 *values;
3662         guint32 token, pclass, parent, sig;
3663         gchar *name;
3664
3665         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3666         if (token)
3667                 return token;
3668
3669         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, &error);
3670         mono_error_raise_exception (&error); /* FIXME don't raise here */
3671         /* FIXME: is this call necessary? */
3672         mono_class_from_mono_type (typeb);
3673         name = mono_string_to_utf8 (fb->name);
3674
3675         /*FIXME this is one more layer of ugliness due how types are created.*/
3676         init_type_builder_generics (fb->type);
3677
3678         /* fb->type does not include the custom modifiers */
3679         /* FIXME: We should do this in one place when a fieldbuilder is created */
3680         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
3681         mono_error_raise_exception (&error); /* FIXME don't raise here */
3682
3683         if (fb->modreq || fb->modopt)
3684                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3685
3686         sig = fieldref_encode_signature (assembly, NULL, type);
3687         g_free (custom);
3688
3689         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, &error);
3690         mono_error_raise_exception (&error); /* FIXME don't raise here */
3691         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3692         
3693         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3694         parent >>= MONO_TYPEDEFORREF_BITS;
3695
3696         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3697
3698         if (assembly->save) {
3699                 alloc_table (table, table->rows + 1);
3700                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3701                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3702                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3703                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3704         }
3705
3706         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3707         table->next_idx ++;
3708         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3709         g_free (name);
3710         return token;
3711 }
3712
3713 static guint32
3714 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3715 {
3716         MonoError error;
3717         SigBuffer buf;
3718         guint32 nargs;
3719         guint32 i, idx;
3720
3721         if (!assembly->save)
3722                 return 0;
3723
3724         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3725         g_assert (helper->type == 2);
3726
3727         if (helper->arguments)
3728                 nargs = mono_array_length (helper->arguments);
3729         else
3730                 nargs = 0;
3731
3732         sigbuffer_init (&buf, 32);
3733
3734         /* Encode calling convention */
3735         /* Change Any to Standard */
3736         if ((helper->call_conv & 0x03) == 0x03)
3737                 helper->call_conv = 0x01;
3738         /* explicit_this implies has_this */
3739         if (helper->call_conv & 0x40)
3740                 helper->call_conv &= 0x20;
3741
3742         if (helper->call_conv == 0) { /* Unmanaged */
3743                 idx = helper->unmanaged_call_conv - 1;
3744         } else {
3745                 /* Managed */
3746                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3747                 if (helper->call_conv & 0x02) /* varargs */
3748                         idx += 0x05;
3749         }
3750
3751         sigbuffer_add_byte (&buf, idx);
3752         sigbuffer_add_value (&buf, nargs);
3753         encode_reflection_type (assembly, helper->return_type, &buf, &error);
3754         if (!is_ok (&error))
3755                 goto fail;
3756         for (i = 0; i < nargs; ++i) {
3757                 MonoArray *modreqs = NULL;
3758                 MonoArray *modopts = NULL;
3759                 MonoReflectionType *pt;
3760
3761                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3762                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3763                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3764                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3765
3766                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, &error);
3767                 if (!is_ok (&error))
3768                         goto fail;
3769                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3770                 encode_reflection_type (assembly, pt, &buf, &error);
3771                 if (!is_ok (&error))
3772                         goto fail;
3773         }
3774         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3775         sigbuffer_free (&buf);
3776
3777         return idx;
3778 fail:
3779         sigbuffer_free (&buf);
3780         mono_error_raise_exception (&error); /* FIXME don't raise here */
3781         g_assert_not_reached ();
3782 }
3783
3784 static guint32 
3785 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3786 {
3787         guint32 idx;
3788         MonoDynamicTable *table;
3789         guint32 *values;
3790
3791         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3792         idx = table->next_idx ++;
3793         table->rows ++;
3794         alloc_table (table, table->rows);
3795         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3796
3797         values [MONO_STAND_ALONE_SIGNATURE] =
3798                 mono_reflection_encode_sighelper (assembly, helper);
3799
3800         return idx;
3801 }
3802
3803 static int
3804 reflection_cc_to_file (int call_conv) {
3805         switch (call_conv & 0x3) {
3806         case 0:
3807         case 1: return MONO_CALL_DEFAULT;
3808         case 2: return MONO_CALL_VARARG;
3809         default:
3810                 g_assert_not_reached ();
3811         }
3812         return 0;
3813 }
3814 #endif /* !DISABLE_REFLECTION_EMIT */
3815
3816 typedef struct {
3817         MonoType *parent;
3818         MonoMethodSignature *sig;
3819         char *name;
3820         guint32 token;
3821 } ArrayMethod;
3822
3823 #ifndef DISABLE_REFLECTION_EMIT
3824 static guint32
3825 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3826 {
3827         MonoError error;
3828         guint32 nparams, i;
3829         GList *tmp;
3830         char *name;
3831         MonoMethodSignature *sig;
3832         ArrayMethod *am;
3833         MonoType *mtype;
3834
3835         name = mono_string_to_utf8 (m->name);
3836         nparams = mono_array_length (m->parameters);
3837         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3838         sig->hasthis = 1;
3839         sig->sentinelpos = -1;
3840         sig->call_convention = reflection_cc_to_file (m->call_conv);
3841         sig->param_count = nparams;
3842         if (m->ret) {
3843                 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3844                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3845         } else
3846                 sig->ret = &mono_defaults.void_class->byval_arg;
3847
3848         mtype = mono_reflection_type_get_handle (m->parent, &error);
3849         mono_error_raise_exception (&error); /* FIXME don't raise here */
3850
3851         for (i = 0; i < nparams; ++i) {
3852                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3853                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3854         }
3855
3856         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3857                 am = (ArrayMethod *)tmp->data;
3858                 if (strcmp (name, am->name) == 0 && 
3859                                 mono_metadata_type_equal (am->parent, mtype) &&
3860                                 mono_metadata_signature_equal (am->sig, sig)) {
3861                         g_free (name);
3862                         g_free (sig);
3863                         m->table_idx = am->token & 0xffffff;
3864                         return am->token;
3865                 }
3866         }
3867         am = g_new0 (ArrayMethod, 1);
3868         am->name = name;
3869         am->sig = sig;
3870         am->parent = mtype;
3871         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3872                 method_encode_signature (assembly, sig));
3873         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3874         m->table_idx = am->token & 0xffffff;
3875         return am->token;
3876 }
3877
3878 /*
3879  * Insert into the metadata tables all the info about the TypeBuilder tb.
3880  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3881  */
3882 static gboolean
3883 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3884 {
3885         MonoDynamicTable *table;
3886         guint *values;
3887         int i, is_object = 0, is_system = 0;
3888         char *n;
3889
3890         mono_error_init (error);
3891
3892         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3893         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3894         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3895         n = mono_string_to_utf8 (tb->name);
3896         if (strcmp (n, "Object") == 0)
3897                 is_object++;
3898         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3899         g_free (n);
3900         n = mono_string_to_utf8 (tb->nspace);
3901         if (strcmp (n, "System") == 0)
3902                 is_system++;
3903         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3904         g_free (n);
3905         if (tb->parent && !(is_system && is_object) && 
3906                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3907                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3908                 return_val_if_nok (error, FALSE);
3909                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3910         } else {
3911                 values [MONO_TYPEDEF_EXTENDS] = 0;
3912         }
3913         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3914         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3915
3916         /*
3917          * if we have explicitlayout or sequentiallayouts, output data in the
3918          * ClassLayout table.
3919          */
3920         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3921                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3922                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3923                 table->rows++;
3924                 alloc_table (table, table->rows);
3925                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3926                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3927                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3928                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3929         }
3930
3931         /* handle interfaces */
3932         if (tb->interfaces) {
3933                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3934                 i = table->rows;
3935                 table->rows += mono_array_length (tb->interfaces);
3936                 alloc_table (table, table->rows);
3937                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3938                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3939                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3940                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3941                         return_val_if_nok (error, FALSE);
3942                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3943                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3944                         values += MONO_INTERFACEIMPL_SIZE;
3945                 }
3946         }
3947
3948         /* handle fields */
3949         if (tb->fields) {
3950                 table = &assembly->tables [MONO_TABLE_FIELD];
3951                 table->rows += tb->num_fields;
3952                 alloc_table (table, table->rows);
3953                 for (i = 0; i < tb->num_fields; ++i) {
3954                         mono_image_get_field_info (
3955                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3956                         return_val_if_nok (error, FALSE);
3957                 }
3958         }
3959
3960         /* handle constructors */
3961         if (tb->ctors) {
3962                 table = &assembly->tables [MONO_TABLE_METHOD];
3963                 table->rows += mono_array_length (tb->ctors);
3964                 alloc_table (table, table->rows);
3965                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3966                         if (!mono_image_get_ctor_info (domain,
3967                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3968                                                        assembly, error))
3969                                 return FALSE;
3970                 }
3971         }
3972
3973         /* handle methods */
3974         if (tb->methods) {
3975                 table = &assembly->tables [MONO_TABLE_METHOD];
3976                 table->rows += tb->num_methods;
3977                 alloc_table (table, table->rows);
3978                 for (i = 0; i < tb->num_methods; ++i) {
3979                         if (!mono_image_get_method_info (
3980                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3981                                 return FALSE;
3982                 }
3983         }
3984
3985         /* Do the same with properties etc.. */
3986         if (tb->events && mono_array_length (tb->events)) {
3987                 table = &assembly->tables [MONO_TABLE_EVENT];
3988                 table->rows += mono_array_length (tb->events);
3989                 alloc_table (table, table->rows);
3990                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3991                 table->rows ++;
3992                 alloc_table (table, table->rows);
3993                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3994                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3995                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3996                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3997                         mono_image_get_event_info (
3998                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
3999                         return_val_if_nok (error, FALSE);
4000                 }
4001         }
4002         if (tb->properties && mono_array_length (tb->properties)) {
4003                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4004                 table->rows += mono_array_length (tb->properties);
4005                 alloc_table (table, table->rows);
4006                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4007                 table->rows ++;
4008                 alloc_table (table, table->rows);
4009                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4010                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4011                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4012                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4013                         mono_image_get_property_info (
4014                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4015                         return_val_if_nok (error, FALSE);
4016                 }
4017         }
4018
4019         /* handle generic parameters */
4020         if (tb->generic_params) {
4021                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4022                 table->rows += mono_array_length (tb->generic_params);
4023                 alloc_table (table, table->rows);
4024                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4025                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4026
4027                         mono_image_get_generic_param_info (
4028                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4029                 }
4030         }
4031
4032         mono_image_add_decl_security (assembly, 
4033                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4034
4035         if (tb->subtypes) {
4036                 MonoDynamicTable *ntable;
4037                 
4038                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4039                 ntable->rows += mono_array_length (tb->subtypes);
4040                 alloc_table (ntable, ntable->rows);
4041                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4042
4043                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4044                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4045
4046                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4047                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4048                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4049                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4050                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4051                                 ntable->next_idx, ntable->rows);*/
4052                         values += MONO_NESTED_CLASS_SIZE;
4053                         ntable->next_idx++;
4054                 }
4055         }
4056
4057         return TRUE;
4058 }
4059 #endif
4060
4061 static void
4062 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4063 {
4064         int i;
4065
4066         mono_ptr_array_append (*types, type);
4067
4068         if (!type->subtypes)
4069                 return;
4070
4071         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4072                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4073                 collect_types (types, subtype);
4074         }
4075 }
4076
4077 static gint
4078 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4079 {
4080         if ((*type1)->table_idx < (*type2)->table_idx)
4081                 return -1;
4082         else
4083                 if ((*type1)->table_idx > (*type2)->table_idx)
4084                         return 1;
4085         else
4086                 return 0;
4087 }
4088
4089 static gboolean
4090 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4091         int i;
4092
4093         mono_error_init (error);
4094         if (!pinfo)
4095                 return TRUE;
4096         for (i = 0; i < mono_array_length (pinfo); ++i) {
4097                 MonoReflectionParamBuilder *pb;
4098                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4099                 if (!pb)
4100                         continue;
4101                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4102                         return FALSE;
4103         }
4104
4105         return TRUE;
4106 }
4107
4108 static gboolean
4109 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4110         int i;
4111
4112         mono_error_init (error);
4113         
4114         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4115                 return FALSE;
4116         if (tb->fields) {
4117                 for (i = 0; i < tb->num_fields; ++i) {
4118                         MonoReflectionFieldBuilder* fb;
4119                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4120                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4121                                 return FALSE;
4122                 }
4123         }
4124         if (tb->events) {
4125                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4126                         MonoReflectionEventBuilder* eb;
4127                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4128                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4129                                 return FALSE;
4130                 }
4131         }
4132         if (tb->properties) {
4133                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4134                         MonoReflectionPropertyBuilder* pb;
4135                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4136                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4137                                 return FALSE;
4138                 }
4139         }
4140         if (tb->ctors) {
4141                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4142                         MonoReflectionCtorBuilder* cb;
4143                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4144                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4145                             !params_add_cattrs (assembly, cb->pinfo, error))
4146                                 return FALSE;
4147                 }
4148         }
4149
4150         if (tb->methods) {
4151                 for (i = 0; i < tb->num_methods; ++i) {
4152                         MonoReflectionMethodBuilder* mb;
4153                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4154                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4155                             !params_add_cattrs (assembly, mb->pinfo, error))
4156                                 return FALSE;
4157                 }
4158         }
4159
4160         if (tb->subtypes) {
4161                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4162                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4163                                 return FALSE;
4164                 }
4165         }
4166
4167         return TRUE;
4168 }
4169
4170 static gboolean
4171 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4172 {
4173         int i;
4174         
4175         mono_error_init (error);
4176
4177         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4178                 return FALSE;
4179
4180         if (moduleb->global_methods) {
4181                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4182                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4183                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4184                             !params_add_cattrs (assembly, mb->pinfo, error))
4185                                 return FALSE;
4186                 }
4187         }
4188
4189         if (moduleb->global_fields) {
4190                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4191                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4192                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4193                                 return FALSE;
4194                 }
4195         }
4196         
4197         if (moduleb->types) {
4198                 for (i = 0; i < moduleb->num_types; ++i) {
4199                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4200                                 return FALSE;
4201                 }
4202         }
4203
4204         return TRUE;
4205 }
4206
4207 static void
4208 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4209 {
4210         MonoDynamicTable *table;
4211         guint32 *values;
4212         char blob_size [6];
4213         guchar hash [20];
4214         char *b = blob_size;
4215         char *dir, *path;
4216
4217         table = &assembly->tables [MONO_TABLE_FILE];
4218         table->rows++;
4219         alloc_table (table, table->rows);
4220         values = table->values + table->next_idx * MONO_FILE_SIZE;
4221         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4222         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4223         if (image_is_dynamic (module->image)) {
4224                 /* This depends on the fact that the main module is emitted last */
4225                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4226                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4227         } else {
4228                 dir = NULL;
4229                 path = g_strdup (module->image->name);
4230         }
4231         mono_sha1_get_digest_from_file (path, hash);
4232         g_free (dir);
4233         g_free (path);
4234         mono_metadata_encode_value (20, b, &b);
4235         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4236         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4237         table->next_idx ++;
4238 }
4239
4240 static void
4241 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4242 {
4243         MonoDynamicTable *table;
4244         int i;
4245
4246         table = &assembly->tables [MONO_TABLE_MODULE];
4247         mb->table_idx = table->next_idx ++;
4248         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4249         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4250         i /= 16;
4251         ++i;
4252         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4253         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4254         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4255         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4256 }
4257
4258 static guint32
4259 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4260         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4261 {
4262         MonoDynamicTable *table;
4263         guint32 *values;
4264         guint32 visib, res;
4265
4266         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4267         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4268                 return 0;
4269
4270         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4271         table->rows++;
4272         alloc_table (table, table->rows);
4273         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4274
4275         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4276         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4277         if (klass->nested_in)
4278                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4279         else
4280                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4281         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4282         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4283
4284         res = table->next_idx;
4285
4286         table->next_idx ++;
4287
4288         /* Emit nested types */
4289         if (klass->ext && klass->ext->nested_classes) {
4290                 GList *tmp;
4291
4292                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4293                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4294         }
4295
4296         return res;
4297 }
4298
4299 static void
4300 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4301         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4302 {
4303         MonoError error;
4304         MonoClass *klass;
4305         guint32 idx, i;
4306
4307         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4308         mono_error_raise_exception (&error); /* FIXME don't raise here */
4309
4310         klass = mono_class_from_mono_type (t);
4311
4312         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4313
4314         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4315                                                                                                    parent_index, assembly);
4316
4317         /* 
4318          * Emit nested types
4319          * We need to do this ourselves since klass->nested_classes is not set up.
4320          */
4321         if (tb->subtypes) {
4322                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4323                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4324         }
4325 }
4326
4327 static void
4328 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4329         guint32 module_index, MonoDynamicImage *assembly)
4330 {
4331         MonoImage *image = module->image;
4332         MonoTableInfo  *t;
4333         guint32 i;
4334
4335         t = &image->tables [MONO_TABLE_TYPEDEF];
4336
4337         for (i = 0; i < t->rows; ++i) {
4338                 MonoError error;
4339                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4340                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4341
4342                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4343                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4344         }
4345 }
4346
4347 static void
4348 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4349 {
4350         MonoDynamicTable *table;
4351         guint32 *values;
4352         guint32 scope, scope_idx, impl, current_idx;
4353         gboolean forwarder = TRUE;
4354         gpointer iter = NULL;
4355         MonoClass *nested;
4356
4357         if (klass->nested_in) {
4358                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4359                 forwarder = FALSE;
4360         } else {
4361                 scope = resolution_scope_from_image (assembly, klass->image);
4362                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4363                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4364                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4365         }
4366
4367         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4368
4369         table->rows++;
4370         alloc_table (table, table->rows);
4371         current_idx = table->next_idx;
4372         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4373
4374         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4375         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4376         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4377         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4378         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4379
4380         table->next_idx++;
4381
4382         while ((nested = mono_class_get_nested_types (klass, &iter)))
4383                 add_exported_type (assemblyb, assembly, nested, current_idx);
4384 }
4385
4386 static void
4387 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4388 {
4389         MonoError error;
4390         MonoClass *klass;
4391         int i;
4392
4393         if (!assemblyb->type_forwarders)
4394                 return;
4395
4396         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4397                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4398                 MonoType *type;
4399                 if (!t)
4400                         continue;
4401
4402                 type = mono_reflection_type_get_handle (t, &error);
4403                 mono_error_assert_ok (&error);
4404                 g_assert (type);
4405
4406                 klass = mono_class_from_mono_type (type);
4407
4408                 add_exported_type (assemblyb, assembly, klass, 0);
4409         }
4410 }
4411
4412 #define align_pointer(base,p)\
4413         do {\
4414                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4415                 if (__diff & 3)\
4416                         (p) += 4 - (__diff & 3);\
4417         } while (0)
4418
4419 static int
4420 compare_constants (const void *a, const void *b)
4421 {
4422         const guint32 *a_values = (const guint32 *)a;
4423         const guint32 *b_values = (const guint32 *)b;
4424         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4425 }
4426
4427 static int
4428 compare_semantics (const void *a, const void *b)
4429 {
4430         const guint32 *a_values = (const guint32 *)a;
4431         const guint32 *b_values = (const guint32 *)b;
4432         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4433         if (assoc)
4434                 return assoc;
4435         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4436 }
4437
4438 static int
4439 compare_custom_attrs (const void *a, const void *b)
4440 {
4441         const guint32 *a_values = (const guint32 *)a;
4442         const guint32 *b_values = (const guint32 *)b;
4443
4444         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4445 }
4446
4447 static int
4448 compare_field_marshal (const void *a, const void *b)
4449 {
4450         const guint32 *a_values = (const guint32 *)a;
4451         const guint32 *b_values = (const guint32 *)b;
4452
4453         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4454 }
4455
4456 static int
4457 compare_nested (const void *a, const void *b)
4458 {
4459         const guint32 *a_values = (const guint32 *)a;
4460         const guint32 *b_values = (const guint32 *)b;
4461
4462         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4463 }
4464
4465 static int
4466 compare_genericparam (const void *a, const void *b)
4467 {
4468         MonoError error;
4469         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4470         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4471
4472         if ((*b_entry)->owner == (*a_entry)->owner) {
4473                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4474                 mono_error_assert_ok (&error);
4475                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4476                 mono_error_assert_ok (&error);
4477                 return 
4478                         mono_type_get_generic_param_num (a_type) -
4479                         mono_type_get_generic_param_num (b_type);
4480         } else
4481                 return (*a_entry)->owner - (*b_entry)->owner;
4482 }
4483
4484 static int
4485 compare_declsecurity_attrs (const void *a, const void *b)
4486 {
4487         const guint32 *a_values = (const guint32 *)a;
4488         const guint32 *b_values = (const guint32 *)b;
4489
4490         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4491 }
4492
4493 static int
4494 compare_interface_impl (const void *a, const void *b)
4495 {
4496         const guint32 *a_values = (const guint32 *)a;
4497         const guint32 *b_values = (const guint32 *)b;
4498
4499         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4500         if (klass)
4501                 return klass;
4502
4503         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4504 }
4505
4506 static void
4507 pad_heap (MonoDynamicStream *sh)
4508 {
4509         if (sh->index & 3) {
4510                 int sz = 4 - (sh->index & 3);
4511                 memset (sh->data + sh->index, 0, sz);
4512                 sh->index += sz;
4513         }
4514 }
4515
4516 struct StreamDesc {
4517         const char *name;
4518         MonoDynamicStream *stream;
4519 };
4520
4521 /*
4522  * build_compressed_metadata() fills in the blob of data that represents the 
4523  * raw metadata as it will be saved in the PE file. The five streams are output 
4524  * and the metadata tables are comnpressed from the guint32 array representation, 
4525  * to the compressed on-disk format.
4526  */
4527 static gboolean
4528 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4529 {
4530         MonoDynamicTable *table;
4531         int i;
4532         guint64 valid_mask = 0;
4533         guint64 sorted_mask;
4534         guint32 heapt_size = 0;
4535         guint32 meta_size = 256; /* allow for header and other stuff */
4536         guint32 table_offset;
4537         guint32 ntables = 0;
4538         guint64 *int64val;
4539         guint32 *int32val;
4540         guint16 *int16val;
4541         MonoImage *meta;
4542         unsigned char *p;
4543         struct StreamDesc stream_desc [5];
4544
4545         mono_error_init (error);
4546
4547         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4548         for (i = 0; i < assembly->gen_params->len; i++) {
4549                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4550                 if (!write_generic_param_entry (assembly, entry, error))
4551                         return FALSE;
4552         }
4553
4554         stream_desc [0].name  = "#~";
4555         stream_desc [0].stream = &assembly->tstream;
4556         stream_desc [1].name  = "#Strings";
4557         stream_desc [1].stream = &assembly->sheap;
4558         stream_desc [2].name  = "#US";
4559         stream_desc [2].stream = &assembly->us;
4560         stream_desc [3].name  = "#Blob";
4561         stream_desc [3].stream = &assembly->blob;
4562         stream_desc [4].name  = "#GUID";
4563         stream_desc [4].stream = &assembly->guid;
4564         
4565         /* tables that are sorted */
4566         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4567                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4568                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4569                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4570                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4571                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4572                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4573         
4574         /* Compute table sizes */
4575         /* the MonoImage has already been created in mono_image_basic_init() */
4576         meta = &assembly->image;
4577
4578         /* sizes should be multiple of 4 */
4579         pad_heap (&assembly->blob);
4580         pad_heap (&assembly->guid);
4581         pad_heap (&assembly->sheap);
4582         pad_heap (&assembly->us);
4583
4584         /* Setup the info used by compute_sizes () */
4585         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4586         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4587         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4588
4589         meta_size += assembly->blob.index;
4590         meta_size += assembly->guid.index;
4591         meta_size += assembly->sheap.index;
4592         meta_size += assembly->us.index;
4593
4594         for (i=0; i < MONO_TABLE_NUM; ++i)
4595                 meta->tables [i].rows = assembly->tables [i].rows;
4596         
4597         for (i = 0; i < MONO_TABLE_NUM; i++){
4598                 if (meta->tables [i].rows == 0)
4599                         continue;
4600                 valid_mask |= (guint64)1 << i;
4601                 ntables ++;
4602                 meta->tables [i].row_size = mono_metadata_compute_size (
4603                         meta, i, &meta->tables [i].size_bitfield);
4604                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4605         }
4606         heapt_size += 24; /* #~ header size */
4607         heapt_size += ntables * 4;
4608         /* make multiple of 4 */
4609         heapt_size += 3;
4610         heapt_size &= ~3;
4611         meta_size += heapt_size;
4612         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4613         p = (unsigned char*)meta->raw_metadata;
4614         /* the metadata signature */
4615         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4616         /* version numbers and 4 bytes reserved */
4617         int16val = (guint16*)p;
4618         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4619         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4620         p += 8;
4621         /* version string */
4622         int32val = (guint32*)p;
4623         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4624         p += 4;
4625         memcpy (p, meta->version, strlen (meta->version));
4626         p += GUINT32_FROM_LE (*int32val);
4627         align_pointer (meta->raw_metadata, p);
4628         int16val = (guint16*)p;
4629         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4630         *int16val = GUINT16_TO_LE (5); /* number of streams */
4631         p += 4;
4632
4633         /*
4634          * write the stream info.
4635          */
4636         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4637         table_offset += 3; table_offset &= ~3;
4638
4639         assembly->tstream.index = heapt_size;
4640         for (i = 0; i < 5; ++i) {
4641                 int32val = (guint32*)p;
4642                 stream_desc [i].stream->offset = table_offset;
4643                 *int32val++ = GUINT32_TO_LE (table_offset);
4644                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4645                 table_offset += GUINT32_FROM_LE (*int32val);
4646                 table_offset += 3; table_offset &= ~3;
4647                 p += 8;
4648                 strcpy ((char*)p, stream_desc [i].name);
4649                 p += strlen (stream_desc [i].name) + 1;
4650                 align_pointer (meta->raw_metadata, p);
4651         }
4652         /* 
4653          * now copy the data, the table stream header and contents goes first.
4654          */
4655         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4656         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4657         int32val = (guint32*)p;
4658         *int32val = GUINT32_TO_LE (0); /* reserved */
4659         p += 4;
4660
4661         *p++ = 2; /* version */
4662         *p++ = 0;
4663
4664         if (meta->idx_string_wide)
4665                 *p |= 0x01;
4666         if (meta->idx_guid_wide)
4667                 *p |= 0x02;
4668         if (meta->idx_blob_wide)
4669                 *p |= 0x04;
4670         ++p;
4671         *p++ = 1; /* reserved */
4672         int64val = (guint64*)p;
4673         *int64val++ = GUINT64_TO_LE (valid_mask);
4674         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4675         p += 16;
4676         int32val = (guint32*)p;
4677         for (i = 0; i < MONO_TABLE_NUM; i++){
4678                 if (meta->tables [i].rows == 0)
4679                         continue;
4680                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4681         }
4682         p = (unsigned char*)int32val;
4683
4684         /* sort the tables that still need sorting */
4685         table = &assembly->tables [MONO_TABLE_CONSTANT];
4686         if (table->rows)
4687                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4688         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4689         if (table->rows)
4690                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4691         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4692         if (table->rows)
4693                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4694         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4695         if (table->rows)
4696                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4697         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4698         if (table->rows)
4699                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4700         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4701         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4702         if (table->rows)
4703                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4704         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4705         if (table->rows)
4706                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4707
4708         /* compress the tables */
4709         for (i = 0; i < MONO_TABLE_NUM; i++){
4710                 int row, col;
4711                 guint32 *values;
4712                 guint32 bitfield = meta->tables [i].size_bitfield;
4713                 if (!meta->tables [i].rows)
4714                         continue;
4715                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4716                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4717                 meta->tables [i].base = (char*)p;
4718                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4719                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4720                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4721                                 switch (mono_metadata_table_size (bitfield, col)) {
4722                                 case 1:
4723                                         *p++ = values [col];
4724                                         break;
4725                                 case 2:
4726                                         *p++ = values [col] & 0xff;
4727                                         *p++ = (values [col] >> 8) & 0xff;
4728                                         break;
4729                                 case 4:
4730                                         *p++ = values [col] & 0xff;
4731                                         *p++ = (values [col] >> 8) & 0xff;
4732                                         *p++ = (values [col] >> 16) & 0xff;
4733                                         *p++ = (values [col] >> 24) & 0xff;
4734                                         break;
4735                                 default:
4736                                         g_assert_not_reached ();
4737                                 }
4738                         }
4739                 }
4740                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4741         }
4742         
4743         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4744         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4745         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4746         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4747         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4748
4749         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4750
4751         return TRUE;
4752 }
4753
4754 /*
4755  * Some tables in metadata need to be sorted according to some criteria, but
4756  * when methods and fields are first created with reflection, they may be assigned a token
4757  * that doesn't correspond to the final token they will get assigned after the sorting.
4758  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4759  * with the reflection objects that represent them. Once all the tables are set up, the 
4760  * reflection objects will contains the correct table index. fixup_method() will fixup the
4761  * tokens for the method with ILGenerator @ilgen.
4762  */
4763 static void
4764 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4765 {
4766         guint32 code_idx = GPOINTER_TO_UINT (value);
4767         MonoReflectionILTokenInfo *iltoken;
4768         MonoReflectionFieldBuilder *field;
4769         MonoReflectionCtorBuilder *ctor;
4770         MonoReflectionMethodBuilder *method;
4771         MonoReflectionTypeBuilder *tb;
4772         MonoReflectionArrayMethod *am;
4773         guint32 i, idx = 0;
4774         unsigned char *target;
4775
4776         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4777                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4778                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4779                 switch (target [3]) {
4780                 case MONO_TABLE_FIELD:
4781                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4782                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4783                                 idx = field->table_idx;
4784                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4785                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4786                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4787                         } else {
4788                                 g_assert_not_reached ();
4789                         }
4790                         break;
4791                 case MONO_TABLE_METHOD:
4792                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4793                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4794                                 idx = method->table_idx;
4795                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4796                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4797                                 idx = ctor->table_idx;
4798                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4799                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4800                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4801                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4802                         } else {
4803                                 g_assert_not_reached ();
4804                         }
4805                         break;
4806                 case MONO_TABLE_TYPEDEF:
4807                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4808                                 g_assert_not_reached ();
4809                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4810                         idx = tb->table_idx;
4811                         break;
4812                 case MONO_TABLE_MEMBERREF:
4813                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4814                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4815                                 idx = am->table_idx;
4816                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4817                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4818                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4819                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4820                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4821                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4822                                 continue;
4823                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4824                                 continue;
4825                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4826                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4827                                 g_assert (is_field_on_inst (f));
4828                                 continue;
4829                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4830                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4831                                 continue;
4832                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4833                                 continue;
4834                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4835                                 continue;
4836                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4837                                 continue;
4838                         } else {
4839                                 g_assert_not_reached ();
4840                         }
4841                         break;
4842                 case MONO_TABLE_METHODSPEC:
4843                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4844                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4845                                 g_assert (mono_method_signature (m)->generic_param_count);
4846                                 continue;
4847                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4848                                 continue;
4849                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4850                                 continue;
4851                         } else {
4852                                 g_assert_not_reached ();
4853                         }
4854                         break;
4855                 default:
4856                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4857                 }
4858                 target [0] = idx & 0xff;
4859                 target [1] = (idx >> 8) & 0xff;
4860                 target [2] = (idx >> 16) & 0xff;
4861         }
4862 }
4863
4864 /*
4865  * fixup_cattrs:
4866  *
4867  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4868  * value is not known when the table is emitted.
4869  */
4870 static void
4871 fixup_cattrs (MonoDynamicImage *assembly)
4872 {
4873         MonoDynamicTable *table;
4874         guint32 *values;
4875         guint32 type, i, idx, token;
4876         MonoObject *ctor;
4877
4878         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4879
4880         for (i = 0; i < table->rows; ++i) {
4881                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4882
4883                 type = values [MONO_CUSTOM_ATTR_TYPE];
4884                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4885                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4886                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4887                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4888                         g_assert (ctor);
4889
4890                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4891                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4892                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4893                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4894                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4895                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4896                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4897                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4898                         }
4899                 }
4900         }
4901 }
4902
4903 static void
4904 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4905 {
4906         MonoDynamicTable *table;
4907         guint32 *values;
4908
4909         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4910         table->rows++;
4911         alloc_table (table, table->rows);
4912         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4913         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4914         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4915         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4916         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4917         table->next_idx++;
4918 }
4919
4920 static void
4921 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4922 {
4923         MonoDynamicTable *table;
4924         guint32 *values;
4925         char blob_size [6];
4926         guchar hash [20];
4927         char *b = blob_size;
4928         char *name, *sname;
4929         guint32 idx, offset;
4930
4931         if (rsrc->filename) {
4932                 name = mono_string_to_utf8 (rsrc->filename);
4933                 sname = g_path_get_basename (name);
4934         
4935                 table = &assembly->tables [MONO_TABLE_FILE];
4936                 table->rows++;
4937                 alloc_table (table, table->rows);
4938                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4939                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4940                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4941                 g_free (sname);
4942
4943                 mono_sha1_get_digest_from_file (name, hash);
4944                 mono_metadata_encode_value (20, b, &b);
4945                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4946                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4947                 g_free (name);
4948                 idx = table->next_idx++;
4949                 rsrc->offset = 0;
4950                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4951         } else {
4952                 char sizebuf [4];
4953                 char *data;
4954                 guint len;
4955                 if (rsrc->data) {
4956                         data = mono_array_addr (rsrc->data, char, 0);
4957                         len = mono_array_length (rsrc->data);
4958                 } else {
4959                         data = NULL;
4960                         len = 0;
4961                 }
4962                 offset = len;
4963                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4964                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4965                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4966                 mono_image_add_stream_data (&assembly->resources, data, len);
4967
4968                 if (!mb->is_main)
4969                         /* 
4970                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4971                          * the main module, but that needs to reference the FILE table
4972                          * which isn't emitted yet.
4973                          */
4974                         return;
4975                 else
4976                         idx = 0;
4977         }
4978
4979         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4980 }
4981
4982 static void
4983 set_version_from_string (MonoString *version, guint32 *values)
4984 {
4985         gchar *ver, *p, *str;
4986         guint32 i;
4987         
4988         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4989         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4990         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4991         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4992         if (!version)
4993                 return;
4994         ver = str = mono_string_to_utf8 (version);
4995         for (i = 0; i < 4; ++i) {
4996                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4997                 switch (*p) {
4998                 case '.':
4999                         p++;
5000                         break;
5001                 case '*':
5002                         /* handle Revision and Build */
5003                         p++;
5004                         break;
5005                 }
5006                 ver = p;
5007         }
5008         g_free (str);
5009 }
5010
5011 static guint32
5012 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5013         gsize len;
5014         guint32 token = 0;
5015         char blob_size [6];
5016         char *b = blob_size;
5017
5018         if (!pkey)
5019                 return token;
5020
5021         len = mono_array_length (pkey);
5022         mono_metadata_encode_value (len, b, &b);
5023         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5024         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5025
5026         assembly->public_key = (guint8 *)g_malloc (len);
5027         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5028         assembly->public_key_len = len;
5029
5030         /* Special case: check for ECMA key (16 bytes) */
5031         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5032                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5033                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5034         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5035                 /* minimum key size (in 2.0) is 384 bits */
5036                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5037         } else {
5038                 /* FIXME - verifier */
5039                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5040                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5041         }
5042         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5043
5044         return token;
5045 }
5046
5047 static void
5048 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5049 {
5050         MonoDynamicTable *table;
5051         MonoDynamicImage *assembly;
5052         MonoReflectionAssemblyBuilder *assemblyb;
5053         MonoDomain *domain;
5054         guint32 *values;
5055         int i;
5056         guint32 module_index;
5057
5058         assemblyb = moduleb->assemblyb;
5059         assembly = moduleb->dynamic_image;
5060         domain = mono_object_domain (assemblyb);
5061
5062         /* Emit ASSEMBLY table */
5063         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5064         alloc_table (table, 1);
5065         values = table->values + MONO_ASSEMBLY_SIZE;
5066         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5067         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5068         if (assemblyb->culture) {
5069                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5070         } else {
5071                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5072         }
5073         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5074         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5075         set_version_from_string (assemblyb->version, values);
5076
5077         /* Emit FILE + EXPORTED_TYPE table */
5078         module_index = 0;
5079         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5080                 int j;
5081                 MonoReflectionModuleBuilder *file_module = 
5082                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5083                 if (file_module != moduleb) {
5084                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5085                         module_index ++;
5086                         if (file_module->types) {
5087                                 for (j = 0; j < file_module->num_types; ++j) {
5088                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5089                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5090                                 }
5091                         }
5092                 }
5093         }
5094         if (assemblyb->loaded_modules) {
5095                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5096                         MonoReflectionModule *file_module = 
5097                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5098                         mono_image_fill_file_table (domain, file_module, assembly);
5099                         module_index ++;
5100                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5101                 }
5102         }
5103         if (assemblyb->type_forwarders)
5104                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5105
5106         /* Emit MANIFESTRESOURCE table */
5107         module_index = 0;
5108         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5109                 int j;
5110                 MonoReflectionModuleBuilder *file_module = 
5111                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5112                 /* The table for the main module is emitted later */
5113                 if (file_module != moduleb) {
5114                         module_index ++;
5115                         if (file_module->resources) {
5116                                 int len = mono_array_length (file_module->resources);
5117                                 for (j = 0; j < len; ++j) {
5118                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5119                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5120                                 }
5121                         }
5122                 }
5123         }               
5124 }
5125
5126 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5127
5128 /*
5129  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5130  * for the modulebuilder @moduleb.
5131  * At the end of the process, method and field tokens are fixed up and the 
5132  * on-disk compressed metadata representation is created.
5133  * Return TRUE on success, or FALSE on failure and sets @error
5134  */
5135 gboolean
5136 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5137 {
5138         MonoDynamicTable *table;
5139         MonoDynamicImage *assembly;
5140         MonoReflectionAssemblyBuilder *assemblyb;
5141         MonoDomain *domain;
5142         MonoPtrArray types;
5143         guint32 *values;
5144         int i, j;
5145
5146         mono_error_init (error);
5147
5148         assemblyb = moduleb->assemblyb;
5149         assembly = moduleb->dynamic_image;
5150         domain = mono_object_domain (assemblyb);
5151
5152         if (assembly->text_rva)
5153                 return TRUE;
5154
5155         assembly->text_rva = START_TEXT_RVA;
5156
5157         if (moduleb->is_main) {
5158                 mono_image_emit_manifest (moduleb);
5159         }
5160
5161         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5162         table->rows = 1; /* .<Module> */
5163         table->next_idx++;
5164         alloc_table (table, table->rows);
5165         /*
5166          * Set the first entry.
5167          */
5168         values = table->values + table->columns;
5169         values [MONO_TYPEDEF_FLAGS] = 0;
5170         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5171         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5172         values [MONO_TYPEDEF_EXTENDS] = 0;
5173         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5174         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5175
5176         /* 
5177          * handle global methods 
5178          * FIXME: test what to do when global methods are defined in multiple modules.
5179          */
5180         if (moduleb->global_methods) {
5181                 table = &assembly->tables [MONO_TABLE_METHOD];
5182                 table->rows += mono_array_length (moduleb->global_methods);
5183                 alloc_table (table, table->rows);
5184                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5185                         if (!mono_image_get_method_info (
5186                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5187                                 goto leave;
5188                 }
5189         }
5190         if (moduleb->global_fields) {
5191                 table = &assembly->tables [MONO_TABLE_FIELD];
5192                 table->rows += mono_array_length (moduleb->global_fields);
5193                 alloc_table (table, table->rows);
5194                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5195                         mono_image_get_field_info (
5196                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5197                                 error);
5198                         if (!is_ok (error))
5199                                 goto leave;
5200                 }
5201         }
5202
5203         table = &assembly->tables [MONO_TABLE_MODULE];
5204         alloc_table (table, 1);
5205         mono_image_fill_module_table (domain, moduleb, assembly);
5206
5207         /* Collect all types into a list sorted by their table_idx */
5208         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5209
5210         if (moduleb->types)
5211                 for (i = 0; i < moduleb->num_types; ++i) {
5212                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5213                         collect_types (&types, type);
5214                 }
5215
5216         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5217         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5218         table->rows += mono_ptr_array_size (types);
5219         alloc_table (table, table->rows);
5220
5221         /*
5222          * Emit type names + namespaces at one place inside the string heap,
5223          * so load_class_names () needs to touch fewer pages.
5224          */
5225         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5226                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5227                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5228         }
5229         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5230                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5231                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5232         }
5233
5234         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5235                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5236                 if (!mono_image_get_type_info (domain, type, assembly, error))
5237                         goto leave_types;
5238         }
5239
5240         /* 
5241          * table->rows is already set above and in mono_image_fill_module_table.
5242          */
5243         /* add all the custom attributes at the end, once all the indexes are stable */
5244         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5245                 goto leave_types;
5246
5247         /* CAS assembly permissions */
5248         if (assemblyb->permissions_minimum)
5249                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5250         if (assemblyb->permissions_optional)
5251                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5252         if (assemblyb->permissions_refused)
5253                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5254
5255         if (!module_add_cattrs (assembly, moduleb, error))
5256                 goto leave_types;
5257
5258         /* fixup tokens */
5259         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5260
5261         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5262          * the final tokens and don't need another fixup pass. */
5263
5264         if (moduleb->global_methods) {
5265                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5266                         MonoReflectionMethodBuilder *mb = mono_array_get (
5267                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5268                         if (!mono_image_add_methodimpl (assembly, mb, error))
5269                                 goto leave_types;
5270                 }
5271         }
5272
5273         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5274                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5275                 if (type->methods) {
5276                         for (j = 0; j < type->num_methods; ++j) {
5277                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5278                                         type->methods, MonoReflectionMethodBuilder*, j);
5279
5280                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5281                                         goto leave_types;
5282                         }
5283                 }
5284         }
5285
5286         fixup_cattrs (assembly);
5287
5288 leave_types:
5289         mono_ptr_array_destroy (types);
5290 leave:
5291
5292         return mono_error_ok (error);
5293 }
5294
5295 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5296
5297 gboolean
5298 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5299 {
5300         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5301 }
5302
5303 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5304
5305
5306 typedef struct {
5307         guint32 import_lookup_table;
5308         guint32 timestamp;
5309         guint32 forwarder;
5310         guint32 name_rva;
5311         guint32 import_address_table_rva;
5312 } MonoIDT;
5313
5314 typedef struct {
5315         guint32 name_rva;
5316         guint32 flags;
5317 } MonoILT;
5318
5319 #ifndef DISABLE_REFLECTION_EMIT
5320
5321 /*
5322  * mono_image_insert_string:
5323  * @module: module builder object
5324  * @str: a string
5325  *
5326  * Insert @str into the user string stream of @module.
5327  */
5328 guint32
5329 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5330 {
5331         MonoDynamicImage *assembly;
5332         guint32 idx;
5333         char buf [16];
5334         char *b = buf;
5335         
5336         if (!module->dynamic_image)
5337                 mono_image_module_basic_init (module);
5338
5339         assembly = module->dynamic_image;
5340         
5341         if (assembly->save) {
5342                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5343                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5344 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5345         {
5346                 char *swapped = g_malloc (2 * mono_string_length (str));
5347                 const char *p = (const char*)mono_string_chars (str);
5348
5349                 swap_with_size (swapped, p, 2, mono_string_length (str));
5350                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5351                 g_free (swapped);
5352         }
5353 #else
5354                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5355 #endif
5356                 mono_image_add_stream_data (&assembly->us, "", 1);
5357         } else {
5358                 idx = assembly->us.index ++;
5359         }
5360
5361         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5362
5363         return MONO_TOKEN_STRING | idx;
5364 }
5365
5366 guint32
5367 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5368 {
5369         MonoClass *klass;
5370         guint32 token = 0;
5371         MonoMethodSignature *sig;
5372
5373         mono_error_init (error);
5374
5375         klass = obj->vtable->klass;
5376         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5377                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5378                 MonoMethodSignature *old;
5379                 guint32 sig_token, parent;
5380                 int nargs, i;
5381
5382                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5383
5384                 nargs = mono_array_length (opt_param_types);
5385                 old = mono_method_signature (method);
5386                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5387
5388                 sig->hasthis = old->hasthis;
5389                 sig->explicit_this = old->explicit_this;
5390                 sig->call_convention = old->call_convention;
5391                 sig->generic_param_count = old->generic_param_count;
5392                 sig->param_count = old->param_count + nargs;
5393                 sig->sentinelpos = old->param_count;
5394                 sig->ret = old->ret;
5395
5396                 for (i = 0; i < old->param_count; i++)
5397                         sig->params [i] = old->params [i];
5398
5399                 for (i = 0; i < nargs; i++) {
5400                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5401                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5402                         if (!is_ok (error)) goto fail;
5403                 }
5404
5405                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5406                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5407                 parent >>= MONO_TYPEDEFORREF_BITS;
5408
5409                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5410                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5411
5412                 sig_token = method_encode_signature (assembly, sig);
5413                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5414         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5415                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5416                 ReflectionMethodBuilder rmb;
5417                 guint32 parent, sig_token;
5418                 int nopt_args, nparams, ngparams, i;
5419
5420                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5421                         goto fail;
5422                 
5423                 rmb.opt_types = opt_param_types;
5424                 nopt_args = mono_array_length (opt_param_types);
5425
5426                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5427                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5428                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5429
5430                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5431                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5432                 sig->call_convention = rmb.call_conv;
5433                 sig->generic_param_count = ngparams;
5434                 sig->param_count = nparams + nopt_args;
5435                 sig->sentinelpos = nparams;
5436                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5437                 if (!is_ok (error)) goto fail;
5438
5439                 for (i = 0; i < nparams; i++) {
5440                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5441                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5442                         if (!is_ok (error)) goto fail;
5443                 }
5444
5445                 for (i = 0; i < nopt_args; i++) {
5446                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5447                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5448                         if (!is_ok (error)) goto fail;
5449                 }
5450
5451                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5452                 if (!is_ok (error))
5453                         goto fail;
5454
5455                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5456                 if (!mono_error_ok (error))
5457                         goto fail;
5458                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5459
5460                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5461                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5462
5463                 char *name = mono_string_to_utf8 (rmb.name);
5464                 token = mono_image_get_varargs_method_token (
5465                         assembly, parent, name, sig_token);
5466                 g_free (name);
5467         } else {
5468                 g_error ("requested method token for %s\n", klass->name);
5469         }
5470
5471         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5472         register_dyn_token (assembly, token, obj);
5473         return token;
5474 fail:
5475         g_assert (!mono_error_ok (error));
5476         return 0;
5477 }
5478
5479 /*
5480  * mono_image_create_token:
5481  * @assembly: a dynamic assembly
5482  * @obj:
5483  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5484  *
5485  * Get a token to insert in the IL code stream for the given MemberInfo.
5486  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5487  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5488  * entry.
5489  */
5490 guint32
5491 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5492                          gboolean create_open_instance, gboolean register_token,
5493                          MonoError *error)
5494 {
5495         MonoClass *klass;
5496         guint32 token = 0;
5497
5498         mono_error_init (error);
5499
5500         klass = obj->vtable->klass;
5501
5502         /* Check for user defined reflection objects */
5503         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5504         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5505                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5506                 return 0;
5507         }
5508
5509         if (strcmp (klass->name, "MethodBuilder") == 0) {
5510                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5511                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5512
5513                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5514                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5515                 else {
5516                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5517                         if (!mono_error_ok (error))
5518                                 return 0;
5519                 }
5520                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5521         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5522                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5523                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5524
5525                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5526                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5527                 else {
5528                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5529                         if (!mono_error_ok (error))
5530                                 return 0;
5531                 }
5532                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5533         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5534                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5535                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5536                 if (tb->generic_params) {
5537                         token = mono_image_get_generic_field_token (assembly, fb);
5538                 } else {
5539                         if (tb->module->dynamic_image == assembly) {
5540                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5541                         } else {
5542                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5543                         }
5544                 }
5545         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5546                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5547                 if (create_open_instance && tb->generic_params) {
5548                         MonoType *type;
5549                         init_type_builder_generics (obj);
5550                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5551                         return_val_if_nok (error, 0);
5552                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5553                         token = mono_metadata_token_from_dor (token);
5554                 } else if (tb->module->dynamic_image == assembly) {
5555                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5556                 } else {
5557                         MonoType *type;
5558                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5559                         return_val_if_nok (error, 0);
5560                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5561                 }
5562         } else if (strcmp (klass->name, "MonoType") == 0) {
5563                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5564                 return_val_if_nok (error, 0);
5565                 MonoClass *mc = mono_class_from_mono_type (type);
5566                 token = mono_metadata_token_from_dor (
5567                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5568         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5569                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5570                 return_val_if_nok (error, 0);
5571                 token = mono_metadata_token_from_dor (
5572                         mono_image_typedef_or_ref (assembly, type));
5573         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5574                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5575                 return_val_if_nok (error, 0);
5576                 token = mono_metadata_token_from_dor (
5577                         mono_image_typedef_or_ref (assembly, type));
5578         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5579                    strcmp (klass->name, "MonoMethod") == 0 ||
5580                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5581                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5582                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5583                 if (m->method->is_inflated) {
5584                         if (create_open_instance)
5585                                 token = mono_image_get_methodspec_token (assembly, m->method);
5586                         else
5587                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5588                 } else if ((m->method->klass->image == &assembly->image) &&
5589                          !m->method->klass->generic_class) {
5590                         static guint32 method_table_idx = 0xffffff;
5591                         if (m->method->klass->wastypebuilder) {
5592                                 /* we use the same token as the one that was assigned
5593                                  * to the Methodbuilder.
5594                                  * FIXME: do the equivalent for Fields.
5595                                  */
5596                                 token = m->method->token;
5597                         } else {
5598                                 /*
5599                                  * Each token should have a unique index, but the indexes are
5600                                  * assigned by managed code, so we don't know about them. An
5601                                  * easy solution is to count backwards...
5602                                  */
5603                                 method_table_idx --;
5604                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5605                         }
5606                 } else {
5607                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5608                 }
5609                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5610         } else if (strcmp (klass->name, "MonoField") == 0) {
5611                 MonoReflectionField *f = (MonoReflectionField *)obj;
5612                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5613                         static guint32 field_table_idx = 0xffffff;
5614                         field_table_idx --;
5615                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5616                 } else {
5617                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5618                 }
5619                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5620         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5621                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5622                 token = mono_image_get_array_token (assembly, m);
5623         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5624                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5625                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5626         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5627                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5628                 return_val_if_nok (error, 0);
5629                 token = mono_metadata_token_from_dor (
5630                         mono_image_typedef_or_ref (assembly, type));
5631         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5632                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5633                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5634                 return_val_if_nok (error, 0);
5635         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5636                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5637                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5638                 if (!mono_error_ok (error))
5639                         return 0;
5640         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5641                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5642                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5643                 if (!mono_error_ok (error))
5644                         return 0;
5645         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5646                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5647                 return_val_if_nok (error, 0);
5648                 token = mono_metadata_token_from_dor (
5649                                 mono_image_typedef_or_ref (assembly, type));
5650         } else {
5651                 g_error ("requested token for %s\n", klass->name);
5652         }
5653
5654         if (register_token)
5655                 mono_image_register_token (assembly, token, obj);
5656
5657         return token;
5658 }
5659
5660 /*
5661  * mono_image_register_token:
5662  *
5663  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5664  * the Module.ResolveXXXToken () methods to work.
5665  */
5666 void
5667 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5668 {
5669         MonoObject *prev;
5670
5671         dynamic_image_lock (assembly);
5672         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5673         if (prev) {
5674                 /* There could be multiple MethodInfo objects with the same token */
5675                 //g_assert (prev == obj);
5676         } else {
5677                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5678         }
5679         dynamic_image_unlock (assembly);
5680 }
5681
5682 static MonoDynamicImage*
5683 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5684 {
5685         static const guchar entrycode [16] = {0xff, 0x25, 0};
5686         MonoDynamicImage *image;
5687         int i;
5688
5689         const char *version;
5690
5691         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5692                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5693         else
5694                 version = mono_get_runtime_info ()->runtime_version;
5695
5696 #if HAVE_BOEHM_GC
5697         /* The MonoGHashTable's need GC tracking */
5698         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5699 #else
5700         image = g_new0 (MonoDynamicImage, 1);
5701 #endif
5702
5703         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5704         
5705         /*g_print ("created image %p\n", image);*/
5706         /* keep in sync with image.c */
5707         image->image.name = assembly_name;
5708         image->image.assembly_name = image->image.name; /* they may be different */
5709         image->image.module_name = module_name;
5710         image->image.version = g_strdup (version);
5711         image->image.md_version_major = 1;
5712         image->image.md_version_minor = 1;
5713         image->image.dynamic = TRUE;
5714
5715         image->image.references = g_new0 (MonoAssembly*, 1);
5716         image->image.references [0] = NULL;
5717
5718         mono_image_init (&image->image);
5719
5720         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");
5721         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5722         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5723         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5724         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5725         image->handleref = g_hash_table_new (NULL, NULL);
5726         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");
5727         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5728         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");
5729         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");
5730         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5731         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5732         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5733         image->gen_params = g_ptr_array_new ();
5734         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5735
5736         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5737         string_heap_init (&image->sheap);
5738         mono_image_add_stream_data (&image->us, "", 1);
5739         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5740         /* import tables... */
5741         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5742         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5743         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5744         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5745         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5746         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5747         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5748         stream_data_align (&image->code);
5749
5750         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5751
5752         for (i=0; i < MONO_TABLE_NUM; ++i) {
5753                 image->tables [i].next_idx = 1;
5754                 image->tables [i].columns = table_sizes [i];
5755         }
5756
5757         image->image.assembly = (MonoAssembly*)assembly;
5758         image->run = assembly->run;
5759         image->save = assembly->save;
5760         image->pe_kind = 0x1; /* ILOnly */
5761         image->machine = 0x14c; /* I386 */
5762         
5763         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5764
5765         dynamic_images_lock ();
5766
5767         if (!dynamic_images)
5768                 dynamic_images = g_ptr_array_new ();
5769
5770         g_ptr_array_add (dynamic_images, image);
5771
5772         dynamic_images_unlock ();
5773
5774         return image;
5775 }
5776 #endif
5777
5778 static void
5779 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5780 {
5781         g_free (key);
5782 }
5783
5784 static void
5785 release_hashtable (MonoGHashTable **hash)
5786 {
5787         if (*hash) {
5788                 mono_g_hash_table_destroy (*hash);
5789                 *hash = NULL;
5790         }
5791 }
5792
5793 void
5794 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5795 {
5796         release_hashtable (&image->token_fixups);
5797         release_hashtable (&image->handleref_managed);
5798         release_hashtable (&image->tokens);
5799         release_hashtable (&image->remapped_tokens);
5800         release_hashtable (&image->generic_def_objects);
5801         release_hashtable (&image->methodspec);
5802 }
5803
5804 // Free dynamic image pass one: Free resources but not image itself
5805 void
5806 mono_dynamic_image_free (MonoDynamicImage *image)
5807 {
5808         MonoDynamicImage *di = image;
5809         GList *list;
5810         int i;
5811
5812         if (di->methodspec)
5813                 mono_g_hash_table_destroy (di->methodspec);
5814         if (di->typespec)
5815                 g_hash_table_destroy (di->typespec);
5816         if (di->typeref)
5817                 g_hash_table_destroy (di->typeref);
5818         if (di->handleref)
5819                 g_hash_table_destroy (di->handleref);
5820         if (di->handleref_managed)
5821                 mono_g_hash_table_destroy (di->handleref_managed);
5822         if (di->tokens)
5823                 mono_g_hash_table_destroy (di->tokens);
5824         if (di->remapped_tokens)
5825                 mono_g_hash_table_destroy (di->remapped_tokens);
5826         if (di->generic_def_objects)
5827                 mono_g_hash_table_destroy (di->generic_def_objects);
5828         if (di->blob_cache) {
5829                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5830                 g_hash_table_destroy (di->blob_cache);
5831         }
5832         if (di->standalonesig_cache)
5833                 g_hash_table_destroy (di->standalonesig_cache);
5834         for (list = di->array_methods; list; list = list->next) {
5835                 ArrayMethod *am = (ArrayMethod *)list->data;
5836                 g_free (am->sig);
5837                 g_free (am->name);
5838                 g_free (am);
5839         }
5840         g_list_free (di->array_methods);
5841         if (di->gen_params) {
5842                 for (i = 0; i < di->gen_params->len; i++) {
5843                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5844                         mono_gc_deregister_root ((char*) &entry->gparam);
5845                         g_free (entry);
5846                 }
5847                 g_ptr_array_free (di->gen_params, TRUE);
5848         }
5849         if (di->token_fixups)
5850                 mono_g_hash_table_destroy (di->token_fixups);
5851         if (di->method_to_table_idx)
5852                 g_hash_table_destroy (di->method_to_table_idx);
5853         if (di->field_to_table_idx)
5854                 g_hash_table_destroy (di->field_to_table_idx);
5855         if (di->method_aux_hash)
5856                 g_hash_table_destroy (di->method_aux_hash);
5857         if (di->vararg_aux_hash)
5858                 g_hash_table_destroy (di->vararg_aux_hash);
5859         g_free (di->strong_name);
5860         g_free (di->win32_res);
5861         if (di->public_key)
5862                 g_free (di->public_key);
5863
5864         /*g_print ("string heap destroy for image %p\n", di);*/
5865         mono_dynamic_stream_reset (&di->sheap);
5866         mono_dynamic_stream_reset (&di->code);
5867         mono_dynamic_stream_reset (&di->resources);
5868         mono_dynamic_stream_reset (&di->us);
5869         mono_dynamic_stream_reset (&di->blob);
5870         mono_dynamic_stream_reset (&di->tstream);
5871         mono_dynamic_stream_reset (&di->guid);
5872         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5873                 g_free (di->tables [i].values);
5874         }
5875
5876         dynamic_images_lock ();
5877
5878         if (dynamic_images)
5879                 g_ptr_array_remove (dynamic_images, di);
5880
5881         dynamic_images_unlock ();
5882 }
5883
5884 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5885 void
5886 mono_dynamic_image_free_image (MonoDynamicImage *image)
5887 {
5888         /* See create_dynamic_mono_image () */
5889 #if HAVE_BOEHM_GC
5890         /* Allocated using GC_MALLOC */
5891 #else
5892         g_free (image);
5893 #endif
5894 }
5895
5896 #ifndef DISABLE_REFLECTION_EMIT
5897
5898 /*
5899  * mono_image_basic_init:
5900  * @assembly: an assembly builder object
5901  *
5902  * Create the MonoImage that represents the assembly builder and setup some
5903  * of the helper hash table and the basic metadata streams.
5904  */
5905 void
5906 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5907 {
5908         MonoDynamicAssembly *assembly;
5909         MonoDynamicImage *image;
5910         MonoDomain *domain = mono_object_domain (assemblyb);
5911         
5912         if (assemblyb->dynamic_assembly)
5913                 return;
5914
5915 #if HAVE_BOEHM_GC
5916         /* assembly->assembly.image might be GC allocated */
5917         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5918 #else
5919         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5920 #endif
5921
5922         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5923         
5924         assembly->assembly.ref_count = 1;
5925         assembly->assembly.dynamic = TRUE;
5926         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5927         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5928         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5929         if (assemblyb->culture)
5930                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5931         else
5932                 assembly->assembly.aname.culture = g_strdup ("");
5933
5934         if (assemblyb->version) {
5935                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5936                         char **version = g_strsplit (vstr, ".", 4);
5937                         char **parts = version;
5938                         assembly->assembly.aname.major = atoi (*parts++);
5939                         assembly->assembly.aname.minor = atoi (*parts++);
5940                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5941                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5942
5943                         g_strfreev (version);
5944                         g_free (vstr);
5945         } else {
5946                         assembly->assembly.aname.major = 0;
5947                         assembly->assembly.aname.minor = 0;
5948                         assembly->assembly.aname.build = 0;
5949                         assembly->assembly.aname.revision = 0;
5950         }
5951
5952         assembly->run = assemblyb->access != 2;
5953         assembly->save = assemblyb->access != 1;
5954         assembly->domain = domain;
5955
5956         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5957         image->initial_image = TRUE;
5958         assembly->assembly.aname.name = image->image.name;
5959         assembly->assembly.image = &image->image;
5960         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5961                 /* -1 to correct for the trailing NULL byte */
5962                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5963                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5964                 }
5965                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5966         }
5967
5968         mono_domain_assemblies_lock (domain);
5969         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5970         mono_domain_assemblies_unlock (domain);
5971
5972         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5973         
5974         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5975         
5976         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5977 }
5978
5979 #endif /* !DISABLE_REFLECTION_EMIT */
5980
5981 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5982
5983 static int
5984 calc_section_size (MonoDynamicImage *assembly)
5985 {
5986         int nsections = 0;
5987
5988         /* alignment constraints */
5989         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5990         g_assert ((assembly->code.index % 4) == 0);
5991         assembly->meta_size += 3;
5992         assembly->meta_size &= ~3;
5993         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5994         g_assert ((assembly->resources.index % 4) == 0);
5995
5996         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5997         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5998         nsections++;
5999
6000         if (assembly->win32_res) {
6001                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6002
6003                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6004                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6005                 nsections++;
6006         }
6007
6008         assembly->sections [MONO_SECTION_RELOC].size = 12;
6009         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6010         nsections++;
6011
6012         return nsections;
6013 }
6014
6015 typedef struct {
6016         guint32 id;
6017         guint32 offset;
6018         GSList *children;
6019         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6020 } ResTreeNode;
6021
6022 static int
6023 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6024 {
6025         ResTreeNode *t1 = (ResTreeNode*)a;
6026         ResTreeNode *t2 = (ResTreeNode*)b;
6027
6028         return t1->id - t2->id;
6029 }
6030
6031 /*
6032  * resource_tree_create:
6033  *
6034  *  Organize the resources into a resource tree.
6035  */
6036 static ResTreeNode *
6037 resource_tree_create (MonoArray *win32_resources)
6038 {
6039         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6040         GSList *l;
6041         int i;
6042
6043         tree = g_new0 (ResTreeNode, 1);
6044         
6045         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6046                 MonoReflectionWin32Resource *win32_res =
6047                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6048
6049                 /* Create node */
6050
6051                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6052                 lang_node = g_new0 (ResTreeNode, 1);
6053                 lang_node->id = win32_res->lang_id;
6054                 lang_node->win32_res = win32_res;
6055
6056                 /* Create type node if neccesary */
6057                 type_node = NULL;
6058                 for (l = tree->children; l; l = l->next)
6059                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6060                                 type_node = (ResTreeNode*)l->data;
6061                                 break;
6062                         }
6063
6064                 if (!type_node) {
6065                         type_node = g_new0 (ResTreeNode, 1);
6066                         type_node->id = win32_res->res_type;
6067
6068                         /* 
6069                          * The resource types have to be sorted otherwise
6070                          * Windows Explorer can't display the version information.
6071                          */
6072                         tree->children = g_slist_insert_sorted (tree->children, 
6073                                 type_node, resource_tree_compare_by_id);
6074                 }
6075
6076                 /* Create res node if neccesary */
6077                 res_node = NULL;
6078                 for (l = type_node->children; l; l = l->next)
6079                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6080                                 res_node = (ResTreeNode*)l->data;
6081                                 break;
6082                         }
6083
6084                 if (!res_node) {
6085                         res_node = g_new0 (ResTreeNode, 1);
6086                         res_node->id = win32_res->res_id;
6087                         type_node->children = g_slist_append (type_node->children, res_node);
6088                 }
6089
6090                 res_node->children = g_slist_append (res_node->children, lang_node);
6091         }
6092
6093         return tree;
6094 }
6095
6096 /*
6097  * resource_tree_encode:
6098  * 
6099  *   Encode the resource tree into the format used in the PE file.
6100  */
6101 static void
6102 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6103 {
6104         char *entries;
6105         MonoPEResourceDir dir;
6106         MonoPEResourceDirEntry dir_entry;
6107         MonoPEResourceDataEntry data_entry;
6108         GSList *l;
6109         guint32 res_id_entries;
6110
6111         /*
6112          * For the format of the resource directory, see the article
6113          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6114          * Matt Pietrek
6115          */
6116
6117         memset (&dir, 0, sizeof (dir));
6118         memset (&dir_entry, 0, sizeof (dir_entry));
6119         memset (&data_entry, 0, sizeof (data_entry));
6120
6121         g_assert (sizeof (dir) == 16);
6122         g_assert (sizeof (dir_entry) == 8);
6123         g_assert (sizeof (data_entry) == 16);
6124
6125         node->offset = p - begin;
6126
6127         /* IMAGE_RESOURCE_DIRECTORY */
6128         res_id_entries = g_slist_length (node->children);
6129         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6130
6131         memcpy (p, &dir, sizeof (dir));
6132         p += sizeof (dir);
6133
6134         /* Reserve space for entries */
6135         entries = p;
6136         p += sizeof (dir_entry) * res_id_entries;
6137
6138         /* Write children */
6139         for (l = node->children; l; l = l->next) {
6140                 ResTreeNode *child = (ResTreeNode*)l->data;
6141
6142                 if (child->win32_res) {
6143                         guint32 size;
6144
6145                         child->offset = p - begin;
6146
6147                         /* IMAGE_RESOURCE_DATA_ENTRY */
6148                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6149                         size = mono_array_length (child->win32_res->res_data);
6150                         data_entry.rde_size = GUINT32_TO_LE (size);
6151
6152                         memcpy (p, &data_entry, sizeof (data_entry));
6153                         p += sizeof (data_entry);
6154
6155                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6156                         p += size;
6157                 } else {
6158                         resource_tree_encode (child, begin, p, &p);
6159                 }
6160         }
6161
6162         /* IMAGE_RESOURCE_ENTRY */
6163         for (l = node->children; l; l = l->next) {
6164                 ResTreeNode *child = (ResTreeNode*)l->data;
6165
6166                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6167                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6168
6169                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6170                 entries += sizeof (dir_entry);
6171         }
6172
6173         *endbuf = p;
6174 }
6175
6176 static void
6177 resource_tree_free (ResTreeNode * node)
6178 {
6179         GSList * list;
6180         for (list = node->children; list; list = list->next)
6181                 resource_tree_free ((ResTreeNode*)list->data);
6182         g_slist_free(node->children);
6183         g_free (node);
6184 }
6185
6186 static void
6187 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6188 {
6189         char *buf;
6190         char *p;
6191         guint32 size, i;
6192         MonoReflectionWin32Resource *win32_res;
6193         ResTreeNode *tree;
6194
6195         if (!assemblyb->win32_resources)
6196                 return;
6197
6198         /*
6199          * Resources are stored in a three level tree inside the PE file.
6200          * - level one contains a node for each type of resource
6201          * - level two contains a node for each resource
6202          * - level three contains a node for each instance of a resource for a
6203          *   specific language.
6204          */
6205
6206         tree = resource_tree_create (assemblyb->win32_resources);
6207
6208         /* Estimate the size of the encoded tree */
6209         size = 0;
6210         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6211                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6212                 size += mono_array_length (win32_res->res_data);
6213         }
6214         /* Directory structure */
6215         size += mono_array_length (assemblyb->win32_resources) * 256;
6216         p = buf = (char *)g_malloc (size);
6217
6218         resource_tree_encode (tree, p, p, &p);
6219
6220         g_assert (p - buf <= size);
6221
6222         assembly->win32_res = (char *)g_malloc (p - buf);
6223         assembly->win32_res_size = p - buf;
6224         memcpy (assembly->win32_res, buf, p - buf);
6225
6226         g_free (buf);
6227         resource_tree_free (tree);
6228 }
6229
6230 static void
6231 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6232 {
6233         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6234         int i;
6235
6236         p += sizeof (MonoPEResourceDir);
6237         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6238                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6239                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6240                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6241                         fixup_resource_directory (res_section, child, rva);
6242                 } else {
6243                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6244                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6245                 }
6246
6247                 p += sizeof (MonoPEResourceDirEntry);
6248         }
6249 }
6250
6251 static void
6252 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6253 {
6254         guint32 dummy;
6255         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6256                 g_error ("WriteFile returned %d\n", GetLastError ());
6257 }
6258
6259 /*
6260  * mono_image_create_pefile:
6261  * @mb: a module builder object
6262  * 
6263  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6264  * assembly->pefile where it can be easily retrieved later in chunks.
6265  */
6266 gboolean
6267 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6268 {
6269         MonoMSDOSHeader *msdos;
6270         MonoDotNetHeader *header;
6271         MonoSectionTable *section;
6272         MonoCLIHeader *cli_header;
6273         guint32 size, image_size, virtual_base, text_offset;
6274         guint32 header_start, section_start, file_offset, virtual_offset;
6275         MonoDynamicImage *assembly;
6276         MonoReflectionAssemblyBuilder *assemblyb;
6277         MonoDynamicStream pefile_stream = {0};
6278         MonoDynamicStream *pefile = &pefile_stream;
6279         int i, nsections;
6280         guint32 *rva, value;
6281         guchar *p;
6282         static const unsigned char msheader[] = {
6283                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6284                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6285                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6286                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6287                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6288                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6289                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6290                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6291         };
6292
6293         mono_error_init (error);
6294
6295         assemblyb = mb->assemblyb;
6296
6297         mono_image_basic_init (assemblyb);
6298         assembly = mb->dynamic_image;
6299
6300         assembly->pe_kind = assemblyb->pe_kind;
6301         assembly->machine = assemblyb->machine;
6302         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6303         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6304         
6305         if (!mono_image_build_metadata (mb, error))
6306                 return FALSE;
6307         
6308
6309         if (mb->is_main && assemblyb->resources) {
6310                 int len = mono_array_length (assemblyb->resources);
6311                 for (i = 0; i < len; ++i)
6312                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6313         }
6314
6315         if (mb->resources) {
6316                 int len = mono_array_length (mb->resources);
6317                 for (i = 0; i < len; ++i)
6318                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6319         }
6320
6321         if (!build_compressed_metadata (assembly, error))
6322                 return FALSE;
6323
6324         if (mb->is_main)
6325                 assembly_add_win32_resources (assembly, assemblyb);
6326
6327         nsections = calc_section_size (assembly);
6328         
6329         /* The DOS header and stub */
6330         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6331         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6332
6333         /* the dotnet header */
6334         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6335
6336         /* the section tables */
6337         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6338
6339         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6340         virtual_offset = VIRT_ALIGN;
6341         image_size = 0;
6342
6343         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6344                 if (!assembly->sections [i].size)
6345                         continue;
6346                 /* align offsets */
6347                 file_offset += FILE_ALIGN - 1;
6348                 file_offset &= ~(FILE_ALIGN - 1);
6349                 virtual_offset += VIRT_ALIGN - 1;
6350                 virtual_offset &= ~(VIRT_ALIGN - 1);
6351
6352                 assembly->sections [i].offset = file_offset;
6353                 assembly->sections [i].rva = virtual_offset;
6354
6355                 file_offset += assembly->sections [i].size;
6356                 virtual_offset += assembly->sections [i].size;
6357                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6358         }
6359
6360         file_offset += FILE_ALIGN - 1;
6361         file_offset &= ~(FILE_ALIGN - 1);
6362
6363         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6364
6365         /* back-patch info */
6366         msdos = (MonoMSDOSHeader*)pefile->data;
6367         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6368
6369         header = (MonoDotNetHeader*)(pefile->data + header_start);
6370         header->pesig [0] = 'P';
6371         header->pesig [1] = 'E';
6372         
6373         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6374         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6375         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6376         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6377         if (assemblyb->pekind == 1) {
6378                 /* it's a dll */
6379                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6380         } else {
6381                 /* it's an exe */
6382                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6383         }
6384
6385         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6386
6387         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6388         header->pe.pe_major = 6;
6389         header->pe.pe_minor = 0;
6390         size = assembly->sections [MONO_SECTION_TEXT].size;
6391         size += FILE_ALIGN - 1;
6392         size &= ~(FILE_ALIGN - 1);
6393         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6394         size = assembly->sections [MONO_SECTION_RSRC].size;
6395         size += FILE_ALIGN - 1;
6396         size &= ~(FILE_ALIGN - 1);
6397         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6398         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6399         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6400         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6401         /* pe_rva_entry_point always at the beginning of the text section */
6402         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6403
6404         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6405         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6406         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6407         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6408         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6409         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6410         size = section_start;
6411         size += FILE_ALIGN - 1;
6412         size &= ~(FILE_ALIGN - 1);
6413         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6414         size = image_size;
6415         size += VIRT_ALIGN - 1;
6416         size &= ~(VIRT_ALIGN - 1);
6417         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6418
6419         /*
6420         // Translate the PEFileKind value to the value expected by the Windows loader
6421         */
6422         {
6423                 short kind;
6424
6425                 /*
6426                 // PEFileKinds.Dll == 1
6427                 // PEFileKinds.ConsoleApplication == 2
6428                 // PEFileKinds.WindowApplication == 3
6429                 //
6430                 // need to get:
6431                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6432                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6433                 */
6434                 if (assemblyb->pekind == 3)
6435                         kind = 2;
6436                 else
6437                         kind = 3;
6438                 
6439                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6440         }    
6441         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6442         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6443         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6444         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6445         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6446         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6447
6448         /* fill data directory entries */
6449
6450         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6451         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6452
6453         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6454         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6455
6456         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6457         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6458         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6459         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6460         /* patch entrypoint name */
6461         if (assemblyb->pekind == 1)
6462                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6463         else
6464                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6465         /* patch imported function RVA name */
6466         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6467         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6468
6469         /* the import table */
6470         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6471         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6472         /* patch imported dll RVA name and other entries in the dir */
6473         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6474         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6475         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6476         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6477         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6478         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6479
6480         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6481         value = (assembly->text_rva + assembly->imp_names_offset);
6482         *p++ = (value) & 0xff;
6483         *p++ = (value >> 8) & (0xff);
6484         *p++ = (value >> 16) & (0xff);
6485         *p++ = (value >> 24) & (0xff);
6486
6487         /* the CLI header info */
6488         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6489         cli_header->ch_size = GUINT32_FROM_LE (72);
6490         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6491         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6492         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6493         if (assemblyb->entry_point) {
6494                 guint32 table_idx = 0;
6495                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6496                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6497                         table_idx = methodb->table_idx;
6498                 } else {
6499                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6500                 }
6501                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6502         } else {
6503                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6504         }
6505         /* The embedded managed resources */
6506         text_offset = assembly->text_rva + assembly->code.index;
6507         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6508         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6509         text_offset += assembly->resources.index;
6510         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6511         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6512         text_offset += assembly->meta_size;
6513         if (assembly->strong_name_size) {
6514                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6515                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6516                 text_offset += assembly->strong_name_size;
6517         }
6518
6519         /* write the section tables and section content */
6520         section = (MonoSectionTable*)(pefile->data + section_start);
6521         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6522                 static const char section_names [][7] = {
6523                         ".text", ".rsrc", ".reloc"
6524                 };
6525                 if (!assembly->sections [i].size)
6526                         continue;
6527                 strcpy (section->st_name, section_names [i]);
6528                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6529                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6530                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6531                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6532                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6533                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6534                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6535                 section ++;
6536         }
6537         
6538         checked_write_file (file, pefile->data, pefile->index);
6539         
6540         mono_dynamic_stream_reset (pefile);
6541         
6542         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6543                 if (!assembly->sections [i].size)
6544                         continue;
6545                 
6546                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6547                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6548                 
6549                 switch (i) {
6550                 case MONO_SECTION_TEXT:
6551                         /* patch entry point */
6552                         p = (guchar*)(assembly->code.data + 2);
6553                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6554                         *p++ = (value) & 0xff;
6555                         *p++ = (value >> 8) & 0xff;
6556                         *p++ = (value >> 16) & 0xff;
6557                         *p++ = (value >> 24) & 0xff;
6558                 
6559                         checked_write_file (file, assembly->code.data, assembly->code.index);
6560                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6561                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6562                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6563                                 
6564
6565                         g_free (assembly->image.raw_metadata);
6566                         break;
6567                 case MONO_SECTION_RELOC: {
6568                         struct {
6569                                 guint32 page_rva;
6570                                 guint32 block_size;
6571                                 guint16 type_and_offset;
6572                                 guint16 term;
6573                         } reloc;
6574                         
6575                         g_assert (sizeof (reloc) == 12);
6576                         
6577                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6578                         reloc.block_size = GUINT32_FROM_LE (12);
6579                         
6580                         /* 
6581                          * the entrypoint is always at the start of the text section 
6582                          * 3 is IMAGE_REL_BASED_HIGHLOW
6583                          * 2 is patch_size_rva - text_rva
6584                          */
6585                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6586                         reloc.term = 0;
6587                         
6588                         checked_write_file (file, &reloc, sizeof (reloc));
6589                         
6590                         break;
6591                 }
6592                 case MONO_SECTION_RSRC:
6593                         if (assembly->win32_res) {
6594
6595                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6596                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6597                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6598                         }
6599                         break;
6600                 default:
6601                         g_assert_not_reached ();
6602                 }
6603         }
6604         
6605         /* check that the file is properly padded */
6606         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6607                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6608         if (! SetEndOfFile (file))
6609                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6610         
6611         mono_dynamic_stream_reset (&assembly->code);
6612         mono_dynamic_stream_reset (&assembly->us);
6613         mono_dynamic_stream_reset (&assembly->blob);
6614         mono_dynamic_stream_reset (&assembly->guid);
6615         mono_dynamic_stream_reset (&assembly->sheap);
6616
6617         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6618         g_hash_table_destroy (assembly->blob_cache);
6619         assembly->blob_cache = NULL;
6620
6621         return TRUE;
6622 }
6623
6624 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6625
6626 gboolean
6627 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6628 {
6629         g_assert_not_reached ();
6630 }
6631
6632 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6633
6634 #ifndef DISABLE_REFLECTION_EMIT
6635
6636 MonoReflectionModule *
6637 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6638 {
6639         MonoError error;
6640         MonoReflectionModule *result = NULL;
6641         char *name;
6642         MonoImage *image;
6643         MonoImageOpenStatus status;
6644         MonoDynamicAssembly *assembly;
6645         guint32 module_count;
6646         MonoImage **new_modules;
6647         gboolean *new_modules_loaded;
6648         
6649         name = mono_string_to_utf8 (fileName);
6650
6651         image = mono_image_open (name, &status);
6652         if (!image) {
6653                 MonoException *exc;
6654                 if (status == MONO_IMAGE_ERROR_ERRNO)
6655                         exc = mono_get_exception_file_not_found (fileName);
6656                 else
6657                         exc = mono_get_exception_bad_image_format (name);
6658                 g_free (name);
6659                 mono_raise_exception (exc);
6660         }
6661
6662         g_free (name);
6663
6664         assembly = ab->dynamic_assembly;
6665         image->assembly = (MonoAssembly*)assembly;
6666
6667         module_count = image->assembly->image->module_count;
6668         new_modules = g_new0 (MonoImage *, module_count + 1);
6669         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6670
6671         if (image->assembly->image->modules)
6672                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6673         if (image->assembly->image->modules_loaded)
6674                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6675         new_modules [module_count] = image;
6676         new_modules_loaded [module_count] = TRUE;
6677         mono_image_addref (image);
6678
6679         g_free (image->assembly->image->modules);
6680         image->assembly->image->modules = new_modules;
6681         image->assembly->image->modules_loaded = new_modules_loaded;
6682         image->assembly->image->module_count ++;
6683
6684         mono_assembly_load_references (image, &status);
6685         if (status) {
6686                 mono_image_close (image);
6687                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6688         }
6689
6690         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6691         mono_error_raise_exception (&error); /* FIXME don't raise here */
6692         return result;
6693 }
6694
6695 #endif /* DISABLE_REFLECTION_EMIT */
6696
6697 /*
6698  * We need to return always the same object for MethodInfo, FieldInfo etc..
6699  * but we need to consider the reflected type.
6700  * type uses a different hash, since it uses custom hash/equal functions.
6701  */
6702
6703 typedef struct {
6704         gpointer item;
6705         MonoClass *refclass;
6706 } ReflectedEntry;
6707
6708 static gboolean
6709 reflected_equal (gconstpointer a, gconstpointer b) {
6710         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6711         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6712
6713         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6714 }
6715
6716 static guint
6717 reflected_hash (gconstpointer a) {
6718         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6719         return mono_aligned_addr_hash (ea->item);
6720 }
6721
6722 #define CHECK_OBJECT(t,p,k)     \
6723         do {    \
6724                 t _obj; \
6725                 ReflectedEntry e;       \
6726                 e.item = (p);   \
6727                 e.refclass = (k);       \
6728                 mono_domain_lock (domain);      \
6729                 if (!domain->refobject_hash)    \
6730                         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");  \
6731                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6732                         mono_domain_unlock (domain);    \
6733                         return _obj;    \
6734                 }       \
6735         mono_domain_unlock (domain); \
6736         } while (0)
6737
6738 #ifdef HAVE_BOEHM_GC
6739 /* ReflectedEntry doesn't need to be GC tracked */
6740 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6741 #define FREE_REFENTRY(entry) g_free ((entry))
6742 #define REFENTRY_REQUIRES_CLEANUP
6743 #else
6744 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6745 /* FIXME: */
6746 #define FREE_REFENTRY(entry)
6747 #endif
6748
6749 #define CACHE_OBJECT(t,p,o,k)   \
6750         do {    \
6751                 t _obj; \
6752         ReflectedEntry pe; \
6753         pe.item = (p); \
6754         pe.refclass = (k); \
6755         mono_domain_lock (domain); \
6756                 if (!domain->refobject_hash)    \
6757                         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");  \
6758         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6759         if (!_obj) { \
6760                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6761                     e->item = (p);      \
6762                     e->refclass = (k);  \
6763                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6764             _obj = o; \
6765         } \
6766                 mono_domain_unlock (domain);    \
6767         return _obj; \
6768         } while (0)
6769
6770 static void
6771 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6772 {
6773         mono_domain_lock (domain);
6774         if (domain->refobject_hash) {
6775         ReflectedEntry pe;
6776                 gpointer orig_pe, orig_value;
6777
6778                 pe.item = o;
6779                 pe.refclass = klass;
6780                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6781                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6782                         FREE_REFENTRY (orig_pe);
6783                 }
6784         }
6785         mono_domain_unlock (domain);
6786 }
6787
6788 #ifdef REFENTRY_REQUIRES_CLEANUP
6789 static void
6790 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6791 {
6792         FREE_REFENTRY (key);
6793 }
6794 #endif
6795
6796 void
6797 mono_reflection_cleanup_domain (MonoDomain *domain)
6798 {
6799         if (domain->refobject_hash) {
6800 /*let's avoid scanning the whole hashtable if not needed*/
6801 #ifdef REFENTRY_REQUIRES_CLEANUP
6802                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6803 #endif
6804                 mono_g_hash_table_destroy (domain->refobject_hash);
6805                 domain->refobject_hash = NULL;
6806         }
6807 }
6808
6809 #ifndef DISABLE_REFLECTION_EMIT
6810 static gpointer
6811 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6812 {
6813         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6814 }
6815
6816 static gpointer
6817 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6818 {
6819         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6820 }
6821
6822 void
6823 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6824 {
6825         MonoDynamicImage *image = moduleb->dynamic_image;
6826         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6827         if (!image) {
6828                 MonoError error;
6829                 int module_count;
6830                 MonoImage **new_modules;
6831                 MonoImage *ass;
6832                 char *name, *fqname;
6833                 /*
6834                  * FIXME: we already created an image in mono_image_basic_init (), but
6835                  * we don't know which module it belongs to, since that is only 
6836                  * determined at assembly save time.
6837                  */
6838                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6839                 name = mono_string_to_utf8 (ab->name);
6840                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6841                 if (!mono_error_ok (&error)) {
6842                         g_free (name);
6843                         mono_error_raise_exception (&error);
6844                 }
6845                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6846
6847                 moduleb->module.image = &image->image;
6848                 moduleb->dynamic_image = image;
6849                 register_module (mono_object_domain (moduleb), moduleb, image);
6850
6851                 /* register the module with the assembly */
6852                 ass = ab->dynamic_assembly->assembly.image;
6853                 module_count = ass->module_count;
6854                 new_modules = g_new0 (MonoImage *, module_count + 1);
6855
6856                 if (ass->modules)
6857                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6858                 new_modules [module_count] = &image->image;
6859                 mono_image_addref (&image->image);
6860
6861                 g_free (ass->modules);
6862                 ass->modules = new_modules;
6863                 ass->module_count ++;
6864         }
6865 }
6866
6867 void
6868 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6869 {
6870         MonoDynamicImage *image = moduleb->dynamic_image;
6871
6872         g_assert (type->type);
6873         image->wrappers_type = mono_class_from_mono_type (type->type);
6874 }
6875
6876 #endif
6877
6878 /*
6879  * mono_assembly_get_object:
6880  * @domain: an app domain
6881  * @assembly: an assembly
6882  *
6883  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6884  */
6885 MonoReflectionAssembly*
6886 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6887 {
6888         MonoError error;
6889         MonoReflectionAssembly *result;
6890         result = mono_assembly_get_object_checked (domain, assembly, &error);
6891         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6892         return result;
6893 }
6894 /*
6895  * mono_assembly_get_object_checked:
6896  * @domain: an app domain
6897  * @assembly: an assembly
6898  *
6899  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6900  */
6901 MonoReflectionAssembly*
6902 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6903 {
6904         MonoReflectionAssembly *res;
6905         
6906         mono_error_init (error);
6907
6908         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6909         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6910         if (!res)
6911                 return NULL;
6912         res->assembly = assembly;
6913
6914         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6915 }
6916
6917
6918
6919 MonoReflectionModule*   
6920 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6921 {
6922         MonoError error;
6923         MonoReflectionModule *result;
6924         result = mono_module_get_object_checked (domain, image, &error);
6925         mono_error_raise_exception (&error);
6926         return result;
6927 }
6928
6929 MonoReflectionModule*
6930 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6931 {
6932         MonoReflectionModule *res;
6933         char* basename;
6934         
6935         mono_error_init (error);
6936         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6937         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6938         if (!res)
6939                 return NULL;
6940
6941         res->image = image;
6942         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6943         if (!assm_obj)
6944                 return NULL;
6945         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6946
6947         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6948         basename = g_path_get_basename (image->name);
6949         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6950         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6951         
6952         g_free (basename);
6953
6954         if (image->assembly->image == image) {
6955                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6956         } else {
6957                 int i;
6958                 res->token = 0;
6959                 if (image->assembly->image->modules) {
6960                         for (i = 0; i < image->assembly->image->module_count; i++) {
6961                                 if (image->assembly->image->modules [i] == image)
6962                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6963                         }
6964                         g_assert (res->token);
6965                 }
6966         }
6967
6968         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6969 }
6970
6971 MonoReflectionModule*
6972 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6973 {
6974         MonoError error;
6975         MonoReflectionModule *result;
6976         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6977         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6978         return result;
6979 }
6980
6981 MonoReflectionModule*
6982 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6983 {
6984         MonoReflectionModule *res;
6985         MonoTableInfo *table;
6986         guint32 cols [MONO_FILE_SIZE];
6987         const char *name;
6988         guint32 i, name_idx;
6989         const char *val;
6990         
6991         mono_error_init (error);
6992
6993         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6994         if (!res)
6995                 return NULL;
6996
6997         table = &image->tables [MONO_TABLE_FILE];
6998         g_assert (table_index < table->rows);
6999         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7000
7001         res->image = NULL;
7002         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7003         if (!assm_obj)
7004                 return NULL;
7005         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7006         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7007
7008         /* Check whenever the row has a corresponding row in the moduleref table */
7009         table = &image->tables [MONO_TABLE_MODULEREF];
7010         for (i = 0; i < table->rows; ++i) {
7011                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7012                 val = mono_metadata_string_heap (image, name_idx);
7013                 if (strcmp (val, name) == 0)
7014                         res->image = image->modules [i];
7015         }
7016
7017         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7018         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7019         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7020         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7021         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7022
7023         return res;
7024 }
7025
7026 static gboolean
7027 verify_safe_for_managed_space (MonoType *type)
7028 {
7029         switch (type->type) {
7030 #ifdef DEBUG_HARDER
7031         case MONO_TYPE_ARRAY:
7032                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7033         case MONO_TYPE_PTR:
7034                 return verify_safe_for_managed_space (type->data.type);
7035         case MONO_TYPE_SZARRAY:
7036                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7037         case MONO_TYPE_GENERICINST: {
7038                 MonoGenericInst *inst = type->data.generic_class->inst;
7039                 int i;
7040                 if (!inst->is_open)
7041                         break;
7042                 for (i = 0; i < inst->type_argc; ++i)
7043                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7044                                 return FALSE;
7045                 return TRUE;
7046         }
7047 #endif
7048         case MONO_TYPE_VAR:
7049         case MONO_TYPE_MVAR:
7050                 return TRUE;
7051         default:
7052                 return TRUE;
7053         }
7054 }
7055
7056 static MonoType*
7057 mono_type_normalize (MonoType *type)
7058 {
7059         int i;
7060         MonoGenericClass *gclass;
7061         MonoGenericInst *ginst;
7062         MonoClass *gtd;
7063         MonoGenericContainer *gcontainer;
7064         MonoType **argv = NULL;
7065         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7066
7067         if (type->type != MONO_TYPE_GENERICINST)
7068                 return type;
7069
7070         gclass = type->data.generic_class;
7071         ginst = gclass->context.class_inst;
7072         if (!ginst->is_open)
7073                 return type;
7074
7075         gtd = gclass->container_class;
7076         gcontainer = gtd->generic_container;
7077         argv = g_newa (MonoType*, ginst->type_argc);
7078
7079         for (i = 0; i < ginst->type_argc; ++i) {
7080                 MonoType *t = ginst->type_argv [i], *norm;
7081                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7082                         is_denorm_gtd = FALSE;
7083                 norm = mono_type_normalize (t);
7084                 argv [i] = norm;
7085                 if (norm != t)
7086                         requires_rebind = TRUE;
7087         }
7088
7089         if (is_denorm_gtd)
7090                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7091
7092         if (requires_rebind) {
7093                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7094                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7095         }
7096
7097         return type;
7098 }
7099 /*
7100  * mono_type_get_object:
7101  * @domain: an app domain
7102  * @type: a type
7103  *
7104  * Return an System.MonoType object representing the type @type.
7105  */
7106 MonoReflectionType*
7107 mono_type_get_object (MonoDomain *domain, MonoType *type)
7108 {
7109         MonoError error;
7110         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7111         mono_error_raise_exception (&error);
7112
7113         return ret;
7114 }
7115
7116 MonoReflectionType*
7117 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7118 {
7119         MonoType *norm_type;
7120         MonoReflectionType *res;
7121         MonoClass *klass;
7122
7123         mono_error_init (error);
7124
7125         klass = mono_class_from_mono_type (type);
7126
7127         /*we must avoid using @type as it might have come
7128          * from a mono_metadata_type_dup and the caller
7129          * expects that is can be freed.
7130          * Using the right type from 
7131          */
7132         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7133
7134         /* void is very common */
7135         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7136                 return (MonoReflectionType*)domain->typeof_void;
7137
7138         /*
7139          * If the vtable of the given class was already created, we can use
7140          * the MonoType from there and avoid all locking and hash table lookups.
7141          * 
7142          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7143          * that the resulting object is different.   
7144          */
7145         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7146                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7147                 if (vtable && vtable->type)
7148                         return (MonoReflectionType *)vtable->type;
7149         }
7150
7151         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7152         mono_domain_lock (domain);
7153         if (!domain->type_hash)
7154                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7155                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7156         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7157                 mono_domain_unlock (domain);
7158                 mono_loader_unlock ();
7159                 return res;
7160         }
7161
7162         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7163          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7164          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7165          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7166          * artifact of how generics are encoded and should be transparent to managed code so we
7167          * need to weed out this diference when retrieving managed System.Type objects.
7168          */
7169         norm_type = mono_type_normalize (type);
7170         if (norm_type != type) {
7171                 res = mono_type_get_object_checked (domain, norm_type, error);
7172                 if (!mono_error_ok (error))
7173                         return NULL;
7174                 mono_g_hash_table_insert (domain->type_hash, type, res);
7175                 mono_domain_unlock (domain);
7176                 mono_loader_unlock ();
7177                 return res;
7178         }
7179
7180         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7181         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7182                 g_assert (0);
7183
7184         if (!verify_safe_for_managed_space (type)) {
7185                 mono_domain_unlock (domain);
7186                 mono_loader_unlock ();
7187                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7188                 return NULL;
7189         }
7190
7191         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7192                 gboolean is_type_done = TRUE;
7193                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7194                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7195                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7196                 */
7197                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7198                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7199
7200                         if (gparam->owner && gparam->owner->is_method) {
7201                                 MonoMethod *method = gparam->owner->owner.method;
7202                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7203                                         is_type_done = FALSE;
7204                         } else if (gparam->owner && !gparam->owner->is_method) {
7205                                 MonoClass *klass = gparam->owner->owner.klass;
7206                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7207                                         is_type_done = FALSE;
7208                         }
7209                 } 
7210
7211                 /* g_assert_not_reached (); */
7212                 /* should this be considered an error condition? */
7213                 if (is_type_done && !type->byref) {
7214                         mono_domain_unlock (domain);
7215                         mono_loader_unlock ();
7216                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7217                 }
7218         }
7219         /* This is stored in vtables/JITted code so it has to be pinned */
7220         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7221         if (!mono_error_ok (error))
7222                 return NULL;
7223
7224         res->type = type;
7225         mono_g_hash_table_insert (domain->type_hash, type, res);
7226
7227         if (type->type == MONO_TYPE_VOID)
7228                 domain->typeof_void = (MonoObject*)res;
7229
7230         mono_domain_unlock (domain);
7231         mono_loader_unlock ();
7232         return res;
7233 }
7234
7235 /*
7236  * mono_method_get_object:
7237  * @domain: an app domain
7238  * @method: a method
7239  * @refclass: the reflected type (can be NULL)
7240  *
7241  * Return an System.Reflection.MonoMethod object representing the method @method.
7242  */
7243 MonoReflectionMethod*
7244 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7245 {
7246         MonoError error;
7247         MonoReflectionMethod *ret = NULL;
7248         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7249         mono_error_raise_exception (&error);
7250         return ret;
7251 }
7252
7253 /*
7254  * mono_method_get_object_checked:
7255  * @domain: an app domain
7256  * @method: a method
7257  * @refclass: the reflected type (can be NULL)
7258  * @error: set on error.
7259  *
7260  * Return an System.Reflection.MonoMethod object representing the method @method.
7261  * Returns NULL and sets @error on error.
7262  */
7263 MonoReflectionMethod*
7264 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7265 {
7266         /*
7267          * We use the same C representation for methods and constructors, but the type 
7268          * name in C# is different.
7269          */
7270         MonoReflectionType *rt;
7271         MonoClass *klass;
7272         MonoReflectionMethod *ret;
7273
7274         mono_error_init (error);
7275
7276         if (method->is_inflated) {
7277                 MonoReflectionGenericMethod *gret;
7278
7279                 if (!refclass)
7280                         refclass = method->klass;
7281                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7282                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7283                         klass = mono_class_get_mono_generic_cmethod_class ();
7284                 } else {
7285                         klass = mono_class_get_mono_generic_method_class ();
7286                 }
7287                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7288                 if (!mono_error_ok (error))
7289                         goto leave;
7290                 gret->method.method = method;
7291
7292                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7293
7294                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7295                 if (!mono_error_ok (error))
7296                     goto leave;
7297
7298                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7299
7300                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7301         }
7302
7303         if (!refclass)
7304                 refclass = method->klass;
7305
7306         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7307         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7308                 klass = mono_class_get_mono_cmethod_class ();
7309         }
7310         else {
7311                 klass = mono_class_get_mono_method_class ();
7312         }
7313         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7314         if (!mono_error_ok (error))
7315                 goto leave;
7316         ret->method = method;
7317
7318         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7319         if (!mono_error_ok (error))
7320                 goto leave;
7321
7322         MONO_OBJECT_SETREF (ret, reftype, rt);
7323
7324         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7325
7326 leave:
7327         g_assert (!mono_error_ok (error));
7328         return NULL;
7329 }
7330
7331 /*
7332  * mono_method_clear_object:
7333  *
7334  *   Clear the cached reflection objects for the dynamic method METHOD.
7335  */
7336 void
7337 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7338 {
7339         MonoClass *klass;
7340         g_assert (method_is_dynamic (method));
7341
7342         klass = method->klass;
7343         while (klass) {
7344                 clear_cached_object (domain, method, klass);
7345                 klass = klass->parent;
7346         }
7347         /* Added by mono_param_get_objects () */
7348         clear_cached_object (domain, &(method->signature), NULL);
7349         klass = method->klass;
7350         while (klass) {
7351                 clear_cached_object (domain, &(method->signature), klass);
7352                 klass = klass->parent;
7353         }
7354 }
7355
7356 /*
7357  * mono_field_get_object:
7358  * @domain: an app domain
7359  * @klass: a type
7360  * @field: a field
7361  *
7362  * Return an System.Reflection.MonoField object representing the field @field
7363  * in class @klass.
7364  */
7365 MonoReflectionField*
7366 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7367 {
7368         MonoError error;
7369         MonoReflectionField *result;
7370         result = mono_field_get_object_checked (domain, klass, field, &error);
7371         mono_error_raise_exception (&error);
7372         return result;
7373 }
7374
7375 /*
7376  * mono_field_get_object_checked:
7377  * @domain: an app domain
7378  * @klass: a type
7379  * @field: a field
7380  * @error: set on error
7381  *
7382  * Return an System.Reflection.MonoField object representing the field @field
7383  * in class @klass. On error, returns NULL and sets @error.
7384  */
7385 MonoReflectionField*
7386 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7387 {
7388         MonoReflectionType *rt;
7389         MonoReflectionField *res;
7390
7391         mono_error_init (error);
7392
7393         CHECK_OBJECT (MonoReflectionField *, field, klass);
7394         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7395         if (!res)
7396                 return NULL;
7397         res->klass = klass;
7398         res->field = field;
7399         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7400
7401         if (is_field_on_inst (field)) {
7402                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7403
7404                 rt = mono_type_get_object_checked (domain, field->type, error);
7405                 if (!mono_error_ok (error))
7406                         return NULL;
7407
7408                 MONO_OBJECT_SETREF (res, type, rt);
7409         } else {
7410                 if (field->type) {
7411                         rt = mono_type_get_object_checked (domain, field->type, error);
7412                         if (!mono_error_ok (error))
7413                                 return NULL;
7414
7415                         MONO_OBJECT_SETREF (res, type, rt);
7416                 }
7417                 res->attrs = mono_field_get_flags (field);
7418         }
7419         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7420 }
7421
7422 /*
7423  * mono_property_get_object:
7424  * @domain: an app domain
7425  * @klass: a type
7426  * @property: a property
7427  *
7428  * Return an System.Reflection.MonoProperty object representing the property @property
7429  * in class @klass.
7430  */
7431 MonoReflectionProperty*
7432 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7433 {
7434         MonoError error;
7435         MonoReflectionProperty *result;
7436         result = mono_property_get_object_checked (domain, klass, property, &error);
7437         mono_error_raise_exception (&error);
7438         return result;
7439 }
7440
7441 /**
7442  * mono_property_get_object:
7443  * @domain: an app domain
7444  * @klass: a type
7445  * @property: a property
7446  * @error: set on error
7447  *
7448  * Return an System.Reflection.MonoProperty object representing the property @property
7449  * in class @klass.  On error returns NULL and sets @error.
7450  */
7451 MonoReflectionProperty*
7452 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7453 {
7454         MonoReflectionProperty *res;
7455
7456         mono_error_init (error);
7457
7458         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7459         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7460         if (!res)
7461                 return NULL;
7462         res->klass = klass;
7463         res->property = property;
7464         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7465 }
7466
7467 /*
7468  * mono_event_get_object:
7469  * @domain: an app domain
7470  * @klass: a type
7471  * @event: a event
7472  *
7473  * Return an System.Reflection.MonoEvent object representing the event @event
7474  * in class @klass.
7475  */
7476 MonoReflectionEvent*
7477 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7478 {
7479         MonoError error;
7480         MonoReflectionEvent *result;
7481         result = mono_event_get_object_checked (domain, klass, event, &error);
7482         mono_error_raise_exception (&error);
7483         return result;
7484 }
7485
7486 /**
7487  * mono_event_get_object_checked:
7488  * @domain: an app domain
7489  * @klass: a type
7490  * @event: a event
7491  * @error: set on error
7492  *
7493  * Return an System.Reflection.MonoEvent object representing the event @event
7494  * in class @klass. On failure sets @error and returns NULL
7495  */
7496 MonoReflectionEvent*
7497 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7498 {
7499         MonoReflectionEvent *res;
7500         MonoReflectionMonoEvent *mono_event;
7501
7502         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7503         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7504         if (!mono_event)
7505                 return NULL;
7506         mono_event->klass = klass;
7507         mono_event->event = event;
7508         res = (MonoReflectionEvent*)mono_event;
7509         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7510 }
7511
7512 /**
7513  * mono_get_reflection_missing_object:
7514  * @domain: Domain where the object lives
7515  *
7516  * Returns the System.Reflection.Missing.Value singleton object
7517  * (of type System.Reflection.Missing).
7518  *
7519  * Used as the value for ParameterInfo.DefaultValue when Optional
7520  * is present
7521  */
7522 static MonoObject *
7523 mono_get_reflection_missing_object (MonoDomain *domain)
7524 {
7525         MonoObject *obj;
7526         static MonoClassField *missing_value_field = NULL;
7527         
7528         if (!missing_value_field) {
7529                 MonoClass *missing_klass;
7530                 missing_klass = mono_class_get_missing_class ();
7531                 mono_class_init (missing_klass);
7532                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7533                 g_assert (missing_value_field);
7534         }
7535         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7536         g_assert (obj);
7537         return obj;
7538 }
7539
7540 static MonoObject*
7541 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7542 {
7543         if (!*dbnull)
7544                 *dbnull = mono_get_dbnull_object (domain);
7545         return *dbnull;
7546 }
7547
7548 static MonoObject*
7549 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7550 {
7551         if (!*reflection_missing)
7552                 *reflection_missing = mono_get_reflection_missing_object (domain);
7553         return *reflection_missing;
7554 }
7555
7556 /*
7557  * mono_param_get_objects:
7558  * @domain: an app domain
7559  * @method: a method
7560  *
7561  * Return an System.Reflection.ParameterInfo array object representing the parameters
7562  * in the method @method.
7563  */
7564 MonoArray*
7565 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7566 {
7567         static MonoClass *System_Reflection_ParameterInfo;
7568         static MonoClass *System_Reflection_ParameterInfo_array;
7569         MonoError error;
7570         MonoArray *res = NULL;
7571         MonoReflectionMethod *member = NULL;
7572         MonoReflectionParameter *param = NULL;
7573         char **names = NULL, **blobs = NULL;
7574         guint32 *types = NULL;
7575         MonoType *type = NULL;
7576         MonoObject *dbnull = NULL;
7577         MonoObject *missing = NULL;
7578         MonoMarshalSpec **mspecs = NULL;
7579         MonoMethodSignature *sig = NULL;
7580         MonoVTable *pinfo_vtable;
7581         MonoReflectionType *rt;
7582         int i;
7583
7584         mono_error_init (&error);
7585         
7586         if (!System_Reflection_ParameterInfo_array) {
7587                 MonoClass *klass;
7588
7589                 klass = mono_class_get_mono_parameter_info_class ();
7590
7591                 mono_memory_barrier ();
7592                 System_Reflection_ParameterInfo = klass; 
7593
7594         
7595                 klass = mono_array_class_get (klass, 1);
7596                 mono_memory_barrier ();
7597                 System_Reflection_ParameterInfo_array = klass;
7598         }
7599
7600         sig = mono_method_signature_checked (method, &error);
7601         if (!mono_error_ok (&error))
7602                 goto leave;
7603
7604         if (!sig->param_count) {
7605                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7606                 if (!res)
7607                         goto leave;
7608
7609                 return res;
7610         }
7611
7612         /* Note: the cache is based on the address of the signature into the method
7613          * since we already cache MethodInfos with the method as keys.
7614          */
7615         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7616
7617         member = mono_method_get_object_checked (domain, method, refclass, &error);
7618         if (!member)
7619                 goto leave;
7620         names = g_new (char *, sig->param_count);
7621         mono_method_get_param_names (method, (const char **) names);
7622
7623         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7624         mono_method_get_marshal_info (method, mspecs);
7625
7626         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7627         if (!res)
7628                 goto leave;
7629
7630         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7631         for (i = 0; i < sig->param_count; ++i) {
7632                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7633                 if (!param)
7634                         goto leave;
7635
7636                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7637                 if (!rt)
7638                         goto leave;
7639
7640                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7641
7642                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7643
7644                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7645
7646                 param->PositionImpl = i;
7647                 param->AttrsImpl = sig->params [i]->attrs;
7648
7649                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7650                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7651                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7652                         else
7653                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7654                 } else {
7655
7656                         if (!blobs) {
7657                                 blobs = g_new0 (char *, sig->param_count);
7658                                 types = g_new0 (guint32, sig->param_count);
7659                                 get_default_param_value_blobs (method, blobs, types); 
7660                         }
7661
7662                         /* Build MonoType for the type from the Constant Table */
7663                         if (!type)
7664                                 type = g_new0 (MonoType, 1);
7665                         type->type = (MonoTypeEnum)types [i];
7666                         type->data.klass = NULL;
7667                         if (types [i] == MONO_TYPE_CLASS)
7668                                 type->data.klass = mono_defaults.object_class;
7669                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7670                                 /* For enums, types [i] contains the base type */
7671
7672                                         type->type = MONO_TYPE_VALUETYPE;
7673                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7674                         } else
7675                                 type->data.klass = mono_class_from_mono_type (type);
7676
7677                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7678
7679                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7680                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7681                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7682                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7683                                 else
7684                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7685                         }
7686                         
7687                 }
7688
7689                 if (mspecs [i + 1]) {
7690                         MonoReflectionMarshalAsAttribute* mobj;
7691                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7692                         if (!mobj)
7693                                 goto leave;
7694                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7695                 }
7696                 
7697                 mono_array_setref (res, i, param);
7698         }
7699
7700 leave:
7701         g_free (names);
7702         g_free (blobs);
7703         g_free (types);
7704         g_free (type);
7705
7706         if (sig) {
7707                 for (i = sig->param_count; i >= 0; i--) {
7708                         if (mspecs [i])
7709                                 mono_metadata_free_marshal_spec (mspecs [i]);
7710                 }
7711         }
7712         g_free (mspecs);
7713
7714         mono_error_raise_exception (&error); /* FIXME don't raise here */
7715         
7716         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7717 }
7718
7719 MonoArray*
7720 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7721 {
7722         return mono_param_get_objects_internal (domain, method, NULL);
7723 }
7724
7725 /*
7726  * mono_method_body_get_object:
7727  * @domain: an app domain
7728  * @method: a method
7729  *
7730  * Return an System.Reflection.MethodBody object representing the method @method.
7731  */
7732 MonoReflectionMethodBody*
7733 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7734 {
7735         MonoError error;
7736         MonoReflectionMethodBody *ret;
7737         MonoMethodHeader *header;
7738         MonoImage *image;
7739         MonoReflectionType *rt;
7740         guint32 method_rva, local_var_sig_token;
7741     char *ptr;
7742         unsigned char format, flags;
7743         int i;
7744
7745         /* for compatibility with .net */
7746     if (method_is_dynamic (method))
7747         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7748
7749         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7750
7751         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7752                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7753             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7754                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7755             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7756                 return NULL;
7757
7758         image = method->klass->image;
7759         header = mono_method_get_header_checked (method, &error);
7760         mono_error_raise_exception (&error); /* FIXME don't raise here */
7761
7762         if (!image_is_dynamic (image)) {
7763                 /* Obtain local vars signature token */
7764                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7765                 ptr = mono_image_rva_map (image, method_rva);
7766                 flags = *(const unsigned char *) ptr;
7767                 format = flags & METHOD_HEADER_FORMAT_MASK;
7768                 switch (format){
7769                 case METHOD_HEADER_TINY_FORMAT:
7770                         local_var_sig_token = 0;
7771                         break;
7772                 case METHOD_HEADER_FAT_FORMAT:
7773                         ptr += 2;
7774                         ptr += 2;
7775                         ptr += 4;
7776                         local_var_sig_token = read32 (ptr);
7777                         break;
7778                 default:
7779                         g_assert_not_reached ();
7780                 }
7781         } else
7782                 local_var_sig_token = 0; //FIXME
7783
7784         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7785         mono_error_raise_exception (&error); /* FIXME don't raise here */
7786
7787         ret->init_locals = header->init_locals;
7788         ret->max_stack = header->max_stack;
7789         ret->local_var_sig_token = local_var_sig_token;
7790         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7791         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7792
7793         /* Locals */
7794         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7795         for (i = 0; i < header->num_locals; ++i) {
7796                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7797                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7798
7799                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7800                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7801
7802                 MONO_OBJECT_SETREF (info, local_type, rt);
7803
7804                 info->is_pinned = header->locals [i]->pinned;
7805                 info->local_index = i;
7806                 mono_array_setref (ret->locals, i, info);
7807         }
7808
7809         /* Exceptions */
7810         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7811         for (i = 0; i < header->num_clauses; ++i) {
7812                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7813                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7814                 MonoExceptionClause *clause = &header->clauses [i];
7815
7816                 info->flags = clause->flags;
7817                 info->try_offset = clause->try_offset;
7818                 info->try_length = clause->try_len;
7819                 info->handler_offset = clause->handler_offset;
7820                 info->handler_length = clause->handler_len;
7821                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7822                         info->filter_offset = clause->data.filter_offset;
7823                 else if (clause->data.catch_class) {
7824                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7825                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7826
7827                         MONO_OBJECT_SETREF (info, catch_type, rt);
7828                 }
7829
7830                 mono_array_setref (ret->clauses, i, info);
7831         }
7832
7833         mono_metadata_free_mh (header);
7834         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7835         return ret;
7836 }
7837
7838 /**
7839  * mono_get_dbnull_object:
7840  * @domain: Domain where the object lives
7841  *
7842  * Returns the System.DBNull.Value singleton object
7843  *
7844  * Used as the value for ParameterInfo.DefaultValue 
7845  */
7846 MonoObject *
7847 mono_get_dbnull_object (MonoDomain *domain)
7848 {
7849         MonoObject *obj;
7850         static MonoClassField *dbnull_value_field = NULL;
7851         
7852         if (!dbnull_value_field) {
7853                 MonoClass *dbnull_klass;
7854                 dbnull_klass = mono_class_get_dbnull_class ();
7855                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7856                 g_assert (dbnull_value_field);
7857         }
7858         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7859         g_assert (obj);
7860         return obj;
7861 }
7862
7863 static void
7864 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7865 {
7866         guint32 param_index, i, lastp, crow = 0;
7867         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7868         gint32 idx;
7869
7870         MonoClass *klass = method->klass;
7871         MonoImage *image = klass->image;
7872         MonoMethodSignature *methodsig = mono_method_signature (method);
7873
7874         MonoTableInfo *constt;
7875         MonoTableInfo *methodt;
7876         MonoTableInfo *paramt;
7877
7878         if (!methodsig->param_count)
7879                 return;
7880
7881         mono_class_init (klass);
7882
7883         if (image_is_dynamic (klass->image)) {
7884                 MonoReflectionMethodAux *aux;
7885                 if (method->is_inflated)
7886                         method = ((MonoMethodInflated*)method)->declaring;
7887                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7888                 if (aux && aux->param_defaults) {
7889                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7890                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7891                 }
7892                 return;
7893         }
7894
7895         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7896         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7897         constt = &image->tables [MONO_TABLE_CONSTANT];
7898
7899         idx = mono_method_get_index (method) - 1;
7900         g_assert (idx != -1);
7901
7902         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7903         if (idx + 1 < methodt->rows)
7904                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7905         else
7906                 lastp = paramt->rows + 1;
7907
7908         for (i = param_index; i < lastp; ++i) {
7909                 guint32 paramseq;
7910
7911                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7912                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7913
7914                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7915                         continue;
7916
7917                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7918                 if (!crow) {
7919                         continue;
7920                 }
7921         
7922                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7923                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7924                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7925         }
7926
7927         return;
7928 }
7929
7930 MonoObject *
7931 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7932 {
7933         MonoError error;
7934         void *retval;
7935         MonoClass *klass;
7936         MonoObject *object;
7937         MonoType *basetype = type;
7938
7939         if (!blob)
7940                 return NULL;
7941         
7942         klass = mono_class_from_mono_type (type);
7943         if (klass->valuetype) {
7944                 object = mono_object_new_checked (domain, klass, &error);
7945                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7946                 retval = ((gchar *) object + sizeof (MonoObject));
7947                 if (klass->enumtype)
7948                         basetype = mono_class_enum_basetype (klass);
7949         } else {
7950                 retval = &object;
7951         }
7952                         
7953         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7954                 return object;
7955         else
7956                 return NULL;
7957 }
7958
7959 static int
7960 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7961         int found_sep;
7962         char *s;
7963         gboolean quoted = FALSE;
7964
7965         memset (assembly, 0, sizeof (MonoAssemblyName));
7966         assembly->culture = "";
7967         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7968
7969         if (*p == '"') {
7970                 quoted = TRUE;
7971                 p++;
7972         }
7973         assembly->name = p;
7974         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7975                 p++;
7976         if (quoted) {
7977                 if (*p != '"')
7978                         return 1;
7979                 *p = 0;
7980                 p++;
7981         }
7982         if (*p != ',')
7983                 return 1;
7984         *p = 0;
7985         /* Remove trailing whitespace */
7986         s = p - 1;
7987         while (*s && g_ascii_isspace (*s))
7988                 *s-- = 0;
7989         p ++;
7990         while (g_ascii_isspace (*p))
7991                 p++;
7992         while (*p) {
7993                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7994                         p += 8;
7995                         assembly->major = strtoul (p, &s, 10);
7996                         if (s == p || *s != '.')
7997                                 return 1;
7998                         p = ++s;
7999                         assembly->minor = strtoul (p, &s, 10);
8000                         if (s == p || *s != '.')
8001                                 return 1;
8002                         p = ++s;
8003                         assembly->build = strtoul (p, &s, 10);
8004                         if (s == p || *s != '.')
8005                                 return 1;
8006                         p = ++s;
8007                         assembly->revision = strtoul (p, &s, 10);
8008                         if (s == p)
8009                                 return 1;
8010                         p = s;
8011                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8012                         p += 8;
8013                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8014                                 assembly->culture = "";
8015                                 p += 7;
8016                         } else {
8017                                 assembly->culture = p;
8018                                 while (*p && *p != ',') {
8019                                         p++;
8020                                 }
8021                         }
8022                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8023                         p += 15;
8024                         if (strncmp (p, "null", 4) == 0) {
8025                                 p += 4;
8026                         } else {
8027                                 int len;
8028                                 gchar *start = p;
8029                                 while (*p && *p != ',') {
8030                                         p++;
8031                                 }
8032                                 len = (p - start + 1);
8033                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8034                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8035                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8036                         }
8037                 } else {
8038                         while (*p && *p != ',')
8039                                 p++;
8040                 }
8041                 found_sep = 0;
8042                 while (g_ascii_isspace (*p) || *p == ',') {
8043                         *p++ = 0;
8044                         found_sep = 1;
8045                         continue;
8046                 }
8047                 /* failed */
8048                 if (!found_sep)
8049                         return 1;
8050         }
8051
8052         return 0;
8053 }
8054
8055 /*
8056  * mono_reflection_parse_type:
8057  * @name: type name
8058  *
8059  * Parse a type name as accepted by the GetType () method and output the info
8060  * extracted in the info structure.
8061  * the name param will be mangled, so, make a copy before passing it to this function.
8062  * The fields in info will be valid until the memory pointed to by name is valid.
8063  *
8064  * See also mono_type_get_name () below.
8065  *
8066  * Returns: 0 on parse error.
8067  */
8068 static int
8069 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8070                              MonoTypeNameParse *info)
8071 {
8072         char *start, *p, *w, *last_point, *startn;
8073         int in_modifiers = 0;
8074         int isbyref = 0, rank = 0, isptr = 0;
8075
8076         start = p = w = name;
8077
8078         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8079         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8080         info->name = info->name_space = NULL;
8081         info->nested = NULL;
8082         info->modifiers = NULL;
8083         info->type_arguments = NULL;
8084
8085         /* last_point separates the namespace from the name */
8086         last_point = NULL;
8087         /* Skips spaces */
8088         while (*p == ' ') p++, start++, w++, name++;
8089
8090         while (*p) {
8091                 switch (*p) {
8092                 case '+':
8093                         *p = 0; /* NULL terminate the name */
8094                         startn = p + 1;
8095                         info->nested = g_list_append (info->nested, startn);
8096                         /* we have parsed the nesting namespace + name */
8097                         if (info->name)
8098                                 break;
8099                         if (last_point) {
8100                                 info->name_space = start;
8101                                 *last_point = 0;
8102                                 info->name = last_point + 1;
8103                         } else {
8104                                 info->name_space = (char *)"";
8105                                 info->name = start;
8106                         }
8107                         break;
8108                 case '.':
8109                         last_point = p;
8110                         break;
8111                 case '\\':
8112                         ++p;
8113                         break;
8114                 case '&':
8115                 case '*':
8116                 case '[':
8117                 case ',':
8118                 case ']':
8119                         in_modifiers = 1;
8120                         break;
8121                 default:
8122                         break;
8123                 }
8124                 if (in_modifiers)
8125                         break;
8126                 // *w++ = *p++;
8127                 p++;
8128         }
8129         
8130         if (!info->name) {
8131                 if (last_point) {
8132                         info->name_space = start;
8133                         *last_point = 0;
8134                         info->name = last_point + 1;
8135                 } else {
8136                         info->name_space = (char *)"";
8137                         info->name = start;
8138                 }
8139         }
8140         while (*p) {
8141                 switch (*p) {
8142                 case '&':
8143                         if (isbyref) /* only one level allowed by the spec */
8144                                 return 0;
8145                         isbyref = 1;
8146                         isptr = 0;
8147                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8148                         *p++ = 0;
8149                         break;
8150                 case '*':
8151                         if (isbyref) /* pointer to ref not okay */
8152                                 return 0;
8153                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8154                         isptr = 1;
8155                         *p++ = 0;
8156                         break;
8157                 case '[':
8158                         if (isbyref) /* array of ref and generic ref are not okay */
8159                                 return 0;
8160                         //Decide if it's an array of a generic argument list
8161                         *p++ = 0;
8162
8163                         if (!*p) //XXX test
8164                                 return 0;
8165                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8166                                 isptr = 0;
8167                                 rank = 1;
8168                                 while (*p) {
8169                                         if (*p == ']')
8170                                                 break;
8171                                         if (*p == ',')
8172                                                 rank++;
8173                                         else if (*p == '*') /* '*' means unknown lower bound */
8174                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8175                                         else
8176                                                 return 0;
8177                                         ++p;
8178                                 }
8179                                 if (*p++ != ']')
8180                                         return 0;
8181                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8182                         } else {
8183                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8184                                         return 0;
8185                                 isptr = 0;
8186                                 info->type_arguments = g_ptr_array_new ();
8187                                 while (*p) {
8188                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8189                                         gboolean fqname = FALSE;
8190
8191                                         g_ptr_array_add (info->type_arguments, subinfo);
8192
8193                                         while (*p == ' ') p++;
8194                                         if (*p == '[') {
8195                                                 p++;
8196                                                 fqname = TRUE;
8197                                         }
8198
8199                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8200                                                 return 0;
8201
8202                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8203                                         if (fqname && (*p != ']')) {
8204                                                 char *aname;
8205
8206                                                 if (*p != ',')
8207                                                         return 0;
8208                                                 *p++ = 0;
8209
8210                                                 aname = p;
8211                                                 while (*p && (*p != ']'))
8212                                                         p++;
8213
8214                                                 if (*p != ']')
8215                                                         return 0;
8216
8217                                                 *p++ = 0;
8218                                                 while (*aname) {
8219                                                         if (g_ascii_isspace (*aname)) {
8220                                                                 ++aname;
8221                                                                 continue;
8222                                                         }
8223                                                         break;
8224                                                 }
8225                                                 if (!*aname ||
8226                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8227                                                         return 0;
8228                                         } else if (fqname && (*p == ']')) {
8229                                                 *p++ = 0;
8230                                         }
8231                                         if (*p == ']') {
8232                                                 *p++ = 0;
8233                                                 break;
8234                                         } else if (!*p) {
8235                                                 return 0;
8236                                         }
8237                                         *p++ = 0;
8238                                 }
8239                         }
8240                         break;
8241                 case ']':
8242                         if (is_recursed)
8243                                 goto end;
8244                         return 0;
8245                 case ',':
8246                         if (is_recursed)
8247                                 goto end;
8248                         *p++ = 0;
8249                         while (*p) {
8250                                 if (g_ascii_isspace (*p)) {
8251                                         ++p;
8252                                         continue;
8253                                 }
8254                                 break;
8255                         }
8256                         if (!*p)
8257                                 return 0; /* missing assembly name */
8258                         if (!assembly_name_to_aname (&info->assembly, p))
8259                                 return 0;
8260                         break;
8261                 default:
8262                         return 0;
8263                 }
8264                 if (info->assembly.name)
8265                         break;
8266         }
8267         // *w = 0; /* terminate class name */
8268  end:
8269         if (!info->name || !*info->name)
8270                 return 0;
8271         if (endptr)
8272                 *endptr = p;
8273         /* add other consistency checks */
8274         return 1;
8275 }
8276
8277
8278 /**
8279  * mono_identifier_unescape_type_name_chars:
8280  * @identifier: the display name of a mono type
8281  *
8282  * Returns:
8283  *  The name in internal form, that is without escaping backslashes.
8284  *
8285  *  The string is modified in place!
8286  */
8287 char*
8288 mono_identifier_unescape_type_name_chars(char* identifier)
8289 {
8290         char *w, *r;
8291         if (!identifier)
8292                 return NULL;
8293         for (w = r = identifier; *r != 0; r++)
8294         {
8295                 char c = *r;
8296                 if (c == '\\') {
8297                         r++;
8298                         if (*r == 0)
8299                                 break;
8300                         c = *r;
8301                 }
8302                 *w = c;
8303                 w++;
8304         }
8305         if (w != r)
8306                 *w = 0;
8307         return identifier;
8308 }
8309
8310 void
8311 mono_identifier_unescape_info (MonoTypeNameParse* info);
8312
8313 static void
8314 unescape_each_type_argument(void* data, void* user_data)
8315 {
8316         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8317         mono_identifier_unescape_info (info);
8318 }
8319
8320 static void
8321 unescape_each_nested_name (void* data, void* user_data)
8322 {
8323         char* nested_name = (char*) data;
8324         mono_identifier_unescape_type_name_chars(nested_name);
8325 }
8326
8327 /**
8328  * mono_identifier_unescape_info:
8329  *
8330  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8331  *
8332  * Returns: nothing.
8333  *
8334  * Destructively updates the info by unescaping the identifiers that
8335  * comprise the type namespace, name, nested types (if any) and
8336  * generic type arguments (if any).
8337  *
8338  * The resulting info has the names in internal form.
8339  *
8340  */
8341 void
8342 mono_identifier_unescape_info (MonoTypeNameParse *info)
8343 {
8344         if (!info)
8345                 return;
8346         mono_identifier_unescape_type_name_chars(info->name_space);
8347         mono_identifier_unescape_type_name_chars(info->name);
8348         // but don't escape info->assembly
8349         if (info->type_arguments)
8350                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8351         if (info->nested)
8352                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8353 }
8354
8355 int
8356 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8357 {
8358         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8359         if (ok) {
8360                 mono_identifier_unescape_info (info);
8361         }
8362         return ok;
8363 }
8364
8365 static MonoType*
8366 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8367 {
8368         gboolean type_resolve = FALSE;
8369         MonoType *type;
8370         MonoImage *rootimage = image;
8371
8372         if (info->assembly.name) {
8373                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8374                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8375                         /* 
8376                          * This could happen in the AOT compiler case when the search hook is not
8377                          * installed.
8378                          */
8379                         assembly = image->assembly;
8380                 if (!assembly) {
8381                         /* then we must load the assembly ourselve - see #60439 */
8382                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8383                         if (!assembly)
8384                                 return NULL;
8385                 }
8386                 image = assembly->image;
8387         } else if (!image) {
8388                 image = mono_defaults.corlib;
8389         }
8390
8391         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8392         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8393                 image = mono_defaults.corlib;
8394                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8395         }
8396
8397         return type;
8398 }
8399
8400 /**
8401  * mono_reflection_get_type_internal:
8402  *
8403  * Returns: may return NULL on success, sets error on failure.
8404  */
8405 static MonoType*
8406 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8407 {
8408         MonoClass *klass;
8409         GList *mod;
8410         int modval;
8411         gboolean bounded = FALSE;
8412         
8413         mono_error_init (error);
8414         if (!image)
8415                 image = mono_defaults.corlib;
8416
8417         if (!rootimage)
8418                 rootimage = mono_defaults.corlib;
8419
8420         if (ignorecase)
8421                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8422         else
8423                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8424
8425         if (!klass)
8426                 return NULL;
8427
8428         for (mod = info->nested; mod; mod = mod->next) {
8429                 gpointer iter = NULL;
8430                 MonoClass *parent;
8431
8432                 parent = klass;
8433                 mono_class_init (parent);
8434
8435                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8436                         char *lastp;
8437                         char *nested_name, *nested_nspace;
8438                         gboolean match = TRUE;
8439
8440                         lastp = strrchr ((const char *)mod->data, '.');
8441                         if (lastp) {
8442                                 /* Nested classes can have namespaces */
8443                                 int nspace_len;
8444
8445                                 nested_name = g_strdup (lastp + 1);
8446                                 nspace_len = lastp - (char*)mod->data;
8447                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8448                                 memcpy (nested_nspace, mod->data, nspace_len);
8449                                 nested_nspace [nspace_len] = '\0';
8450
8451                         } else {
8452                                 nested_name = (char *)mod->data;
8453                                 nested_nspace = NULL;
8454                         }
8455
8456                         if (nested_nspace) {
8457                                 if (ignorecase) {
8458                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8459                                                 match = FALSE;
8460                                 } else {
8461                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8462                                                 match = FALSE;
8463                                 }
8464                         }
8465                         if (match) {
8466                                 if (ignorecase) {
8467                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8468                                                 match = FALSE;
8469                                 } else {
8470                                         if (strcmp (klass->name, nested_name) != 0)
8471                                                 match = FALSE;
8472                                 }
8473                         }
8474                         if (lastp) {
8475                                 g_free (nested_name);
8476                                 g_free (nested_nspace);
8477                         }
8478                         if (match)
8479                                 break;
8480                 }
8481
8482                 if (!klass)
8483                         break;
8484         }
8485         if (!klass)
8486                 return NULL;
8487
8488         if (info->type_arguments) {
8489                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8490                 MonoReflectionType *the_type;
8491                 MonoType *instance;
8492                 int i;
8493
8494                 for (i = 0; i < info->type_arguments->len; i++) {
8495                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8496
8497                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8498                         if (!type_args [i]) {
8499                                 g_free (type_args);
8500                                 return NULL;
8501                         }
8502                 }
8503
8504                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8505                 if (!the_type)
8506                         return NULL;
8507
8508                 instance = mono_reflection_bind_generic_parameters (
8509                         the_type, info->type_arguments->len, type_args);
8510
8511                 g_free (type_args);
8512                 if (!instance)
8513                         return NULL;
8514
8515                 klass = mono_class_from_mono_type (instance);
8516         }
8517
8518         for (mod = info->modifiers; mod; mod = mod->next) {
8519                 modval = GPOINTER_TO_UINT (mod->data);
8520                 if (!modval) { /* byref: must be last modifier */
8521                         return &klass->this_arg;
8522                 } else if (modval == -1) {
8523                         klass = mono_ptr_class_get (&klass->byval_arg);
8524                 } else if (modval == -2) {
8525                         bounded = TRUE;
8526                 } else { /* array rank */
8527                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8528                 }
8529         }
8530
8531         return &klass->byval_arg;
8532 }
8533
8534 /*
8535  * mono_reflection_get_type:
8536  * @image: a metadata context
8537  * @info: type description structure
8538  * @ignorecase: flag for case-insensitive string compares
8539  * @type_resolve: whenever type resolve was already tried
8540  *
8541  * Build a MonoType from the type description in @info.
8542  * 
8543  */
8544
8545 MonoType*
8546 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8547         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8548 }
8549
8550 static MonoType*
8551 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8552 {
8553         MonoReflectionAssemblyBuilder *abuilder;
8554         MonoType *type;
8555         int i;
8556
8557         mono_error_init (error);
8558         g_assert (assembly_is_dynamic (assembly));
8559         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8560         if (!abuilder)
8561                 return NULL;
8562
8563         /* Enumerate all modules */
8564
8565         type = NULL;
8566         if (abuilder->modules) {
8567                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8568                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8569                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8570                         if (type)
8571                                 break;
8572                         if (!mono_error_ok (error))
8573                                 return NULL;
8574                 }
8575         }
8576
8577         if (!type && abuilder->loaded_modules) {
8578                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8579                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8580                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8581                         if (type)
8582                                 break;
8583                         if (!mono_error_ok (error))
8584                                 return NULL;
8585                 }
8586         }
8587
8588         return type;
8589 }
8590         
8591 MonoType*
8592 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8593 {
8594         MonoError error;
8595         MonoType *type;
8596         MonoReflectionAssembly *assembly;
8597         GString *fullName;
8598         GList *mod;
8599
8600         if (image && image_is_dynamic (image))
8601                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8602         else {
8603                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8604         }
8605         if (!mono_error_ok (&error))
8606                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8607
8608         if (type)
8609                 return type;
8610         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8611                 return NULL;
8612
8613         if (type_resolve) {
8614                 if (*type_resolve) 
8615                         return NULL;
8616                 else
8617                         *type_resolve = TRUE;
8618         }
8619         
8620         /* Reconstruct the type name */
8621         fullName = g_string_new ("");
8622         if (info->name_space && (info->name_space [0] != '\0'))
8623                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8624         else
8625                 g_string_printf (fullName, "%s", info->name);
8626         for (mod = info->nested; mod; mod = mod->next)
8627                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8628
8629         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8630         mono_error_raise_exception (&error); /* FIXME don't raise here */
8631
8632         if (assembly) {
8633                 if (assembly_is_dynamic (assembly->assembly))
8634                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8635                                                                           info, ignorecase, &error);
8636                 else
8637                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8638                                                                   info, ignorecase, &error);
8639         }
8640         g_string_free (fullName, TRUE);
8641         if (!mono_error_ok (&error))
8642                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8643         return type;
8644 }
8645
8646 void
8647 mono_reflection_free_type_info (MonoTypeNameParse *info)
8648 {
8649         g_list_free (info->modifiers);
8650         g_list_free (info->nested);
8651
8652         if (info->type_arguments) {
8653                 int i;
8654
8655                 for (i = 0; i < info->type_arguments->len; i++) {
8656                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8657
8658                         mono_reflection_free_type_info (subinfo);
8659                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8660                         g_free (subinfo);
8661                 }
8662
8663                 g_ptr_array_free (info->type_arguments, TRUE);
8664         }
8665 }
8666
8667 /*
8668  * mono_reflection_type_from_name:
8669  * @name: type name.
8670  * @image: a metadata context (can be NULL).
8671  *
8672  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8673  * it defaults to get the type from @image or, if @image is NULL or loading
8674  * from it fails, uses corlib.
8675  * 
8676  */
8677 MonoType*
8678 mono_reflection_type_from_name (char *name, MonoImage *image)
8679 {
8680         MonoType *type = NULL;
8681         MonoTypeNameParse info;
8682         char *tmp;
8683
8684         /* Make a copy since parse_type modifies its argument */
8685         tmp = g_strdup (name);
8686         
8687         /*g_print ("requested type %s\n", str);*/
8688         if (mono_reflection_parse_type (tmp, &info)) {
8689                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8690         }
8691
8692         g_free (tmp);
8693         mono_reflection_free_type_info (&info);
8694         return type;
8695 }
8696
8697 /*
8698  * mono_reflection_get_token:
8699  *
8700  *   Return the metadata token of OBJ which should be an object
8701  * representing a metadata element.
8702  */
8703 guint32
8704 mono_reflection_get_token (MonoObject *obj)
8705 {
8706         MonoError error;
8707         MonoClass *klass;
8708         guint32 token = 0;
8709
8710         klass = obj->vtable->klass;
8711
8712         if (strcmp (klass->name, "MethodBuilder") == 0) {
8713                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8714
8715                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8716         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8717                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8718
8719                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8720         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8721                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8722
8723                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8724         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8725                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8726                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8727         } else if (strcmp (klass->name, "MonoType") == 0) {
8728                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8729                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8730                 MonoClass *mc = mono_class_from_mono_type (type);
8731                 if (!mono_class_init (mc))
8732                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8733
8734                 token = mc->type_token;
8735         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8736                    strcmp (klass->name, "MonoMethod") == 0 ||
8737                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8738                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8739                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8740                 if (m->method->is_inflated) {
8741                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8742                         return inflated->declaring->token;
8743                 } else {
8744                         token = m->method->token;
8745                 }
8746         } else if (strcmp (klass->name, "MonoField") == 0) {
8747                 MonoReflectionField *f = (MonoReflectionField*)obj;
8748
8749                 if (is_field_on_inst (f->field)) {
8750                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8751
8752                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8753                                 int field_index = f->field - dgclass->fields;
8754                                 MonoObject *obj;
8755
8756                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8757                                 obj = dgclass->field_objects [field_index];
8758                                 return mono_reflection_get_token (obj);
8759                         }
8760                 }
8761                 token = mono_class_get_field_token (f->field);
8762         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8763                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8764
8765                 token = mono_class_get_property_token (p->property);
8766         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8767                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8768
8769                 token = mono_class_get_event_token (p->event);
8770         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8771                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8772                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8773                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8774
8775                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8776         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8777                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8778
8779                 token = m->token;
8780         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8781                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8782         } else {
8783                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8784                 MonoException *ex = mono_get_exception_not_implemented (msg);
8785                 g_free (msg);
8786                 mono_raise_exception (ex);
8787         }
8788
8789         return token;
8790 }
8791
8792 static MonoClass*
8793 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8794 {
8795         char *n;
8796         MonoType *t;
8797         int slen = mono_metadata_decode_value (p, &p);
8798
8799         mono_error_init (error);
8800
8801         n = (char *)g_memdup (p, slen + 1);
8802         n [slen] = 0;
8803         t = mono_reflection_type_from_name (n, image);
8804         if (!t) {
8805                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8806                 /* We don't free n, it's consumed by mono_error */
8807                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8808                 return NULL;
8809         }
8810         g_free (n);
8811         p += slen;
8812         *end = p;
8813         return mono_class_from_mono_type (t);
8814 }
8815
8816 static void*
8817 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8818 {
8819         int slen, type = t->type;
8820         MonoClass *tklass = t->data.klass;
8821
8822         mono_error_init (error);
8823
8824 handle_enum:
8825         switch (type) {
8826         case MONO_TYPE_U1:
8827         case MONO_TYPE_I1:
8828         case MONO_TYPE_BOOLEAN: {
8829                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8830                 *bval = *p;
8831                 *end = p + 1;
8832                 return bval;
8833         }
8834         case MONO_TYPE_CHAR:
8835         case MONO_TYPE_U2:
8836         case MONO_TYPE_I2: {
8837                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8838                 *val = read16 (p);
8839                 *end = p + 2;
8840                 return val;
8841         }
8842 #if SIZEOF_VOID_P == 4
8843         case MONO_TYPE_U:
8844         case MONO_TYPE_I:
8845 #endif
8846         case MONO_TYPE_R4:
8847         case MONO_TYPE_U4:
8848         case MONO_TYPE_I4: {
8849                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8850                 *val = read32 (p);
8851                 *end = p + 4;
8852                 return val;
8853         }
8854 #if SIZEOF_VOID_P == 8
8855         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8856         case MONO_TYPE_I:
8857 #endif
8858         case MONO_TYPE_U8:
8859         case MONO_TYPE_I8: {
8860                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8861                 *val = read64 (p);
8862                 *end = p + 8;
8863                 return val;
8864         }
8865         case MONO_TYPE_R8: {
8866                 double *val = (double *)g_malloc (sizeof (double));
8867                 readr8 (p, val);
8868                 *end = p + 8;
8869                 return val;
8870         }
8871         case MONO_TYPE_VALUETYPE:
8872                 if (t->data.klass->enumtype) {
8873                         type = mono_class_enum_basetype (t->data.klass)->type;
8874                         goto handle_enum;
8875                 } else {
8876                         MonoClass *k =  t->data.klass;
8877                         
8878                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8879                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8880                                 *val = read64 (p);
8881                                 *end = p + 8;
8882                                 return val;
8883                         }
8884                 }
8885                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8886                 break;
8887                 
8888         case MONO_TYPE_STRING:
8889                 if (*p == (char)0xFF) {
8890                         *end = p + 1;
8891                         return NULL;
8892                 }
8893                 slen = mono_metadata_decode_value (p, &p);
8894                 *end = p + slen;
8895                 return mono_string_new_len (mono_domain_get (), p, slen);
8896         case MONO_TYPE_CLASS: {
8897                 MonoReflectionType *rt;
8898                 char *n;
8899                 MonoType *t;
8900                 if (*p == (char)0xFF) {
8901                         *end = p + 1;
8902                         return NULL;
8903                 }
8904 handle_type:
8905                 slen = mono_metadata_decode_value (p, &p);
8906                 n = (char *)g_memdup (p, slen + 1);
8907                 n [slen] = 0;
8908                 t = mono_reflection_type_from_name (n, image);
8909                 if (!t) {
8910                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8911                         /* We don't free n, it's consumed by mono_error */
8912                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8913                         return NULL;
8914                 }
8915                 g_free (n);
8916                 *end = p + slen;
8917
8918                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8919                 if (!mono_error_ok (error))
8920                         return NULL;
8921
8922                 return rt;
8923         }
8924         case MONO_TYPE_OBJECT: {
8925                 char subt = *p++;
8926                 MonoObject *obj;
8927                 MonoClass *subc = NULL;
8928                 void *val;
8929
8930                 if (subt == 0x50) {
8931                         goto handle_type;
8932                 } else if (subt == 0x0E) {
8933                         type = MONO_TYPE_STRING;
8934                         goto handle_enum;
8935                 } else if (subt == 0x1D) {
8936                         MonoType simple_type = {{0}};
8937                         int etype = *p;
8938                         p ++;
8939
8940                         type = MONO_TYPE_SZARRAY;
8941                         if (etype == 0x50) {
8942                                 tklass = mono_defaults.systemtype_class;
8943                         } else if (etype == 0x55) {
8944                                 tklass = load_cattr_enum_type (image, p, &p, error);
8945                                 if (!mono_error_ok (error))
8946                                         return NULL;
8947                         } else {
8948                                 if (etype == 0x51)
8949                                         /* See Partition II, Appendix B3 */
8950                                         etype = MONO_TYPE_OBJECT;
8951                                 simple_type.type = (MonoTypeEnum)etype;
8952                                 tklass = mono_class_from_mono_type (&simple_type);
8953                         }
8954                         goto handle_enum;
8955                 } else if (subt == 0x55) {
8956                         char *n;
8957                         MonoType *t;
8958                         slen = mono_metadata_decode_value (p, &p);
8959                         n = (char *)g_memdup (p, slen + 1);
8960                         n [slen] = 0;
8961                         t = mono_reflection_type_from_name (n, image);
8962                         if (!t) {
8963                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8964                                 /* We don't free n, it's consumed by mono_error */
8965                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8966                                 return NULL;
8967                         }
8968                         g_free (n);
8969                         p += slen;
8970                         subc = mono_class_from_mono_type (t);
8971                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8972                         MonoType simple_type = {{0}};
8973                         simple_type.type = (MonoTypeEnum)subt;
8974                         subc = mono_class_from_mono_type (&simple_type);
8975                 } else {
8976                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8977                 }
8978                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8979                 obj = NULL;
8980                 if (mono_error_ok (error)) {
8981                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8982                         g_assert (!subc->has_references);
8983                         if (mono_error_ok (error))
8984                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8985                 }
8986
8987                 g_free (val);
8988                 return obj;
8989         }
8990         case MONO_TYPE_SZARRAY: {
8991                 MonoArray *arr;
8992                 guint32 i, alen, basetype;
8993                 alen = read32 (p);
8994                 p += 4;
8995                 if (alen == 0xffffffff) {
8996                         *end = p;
8997                         return NULL;
8998                 }
8999                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9000                 basetype = tklass->byval_arg.type;
9001                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9002                         basetype = mono_class_enum_basetype (tklass)->type;
9003                 switch (basetype)
9004                 {
9005                         case MONO_TYPE_U1:
9006                         case MONO_TYPE_I1:
9007                         case MONO_TYPE_BOOLEAN:
9008                                 for (i = 0; i < alen; i++) {
9009                                         MonoBoolean val = *p++;
9010                                         mono_array_set (arr, MonoBoolean, i, val);
9011                                 }
9012                                 break;
9013                         case MONO_TYPE_CHAR:
9014                         case MONO_TYPE_U2:
9015                         case MONO_TYPE_I2:
9016                                 for (i = 0; i < alen; i++) {
9017                                         guint16 val = read16 (p);
9018                                         mono_array_set (arr, guint16, i, val);
9019                                         p += 2;
9020                                 }
9021                                 break;
9022                         case MONO_TYPE_R4:
9023                         case MONO_TYPE_U4:
9024                         case MONO_TYPE_I4:
9025                                 for (i = 0; i < alen; i++) {
9026                                         guint32 val = read32 (p);
9027                                         mono_array_set (arr, guint32, i, val);
9028                                         p += 4;
9029                                 }
9030                                 break;
9031                         case MONO_TYPE_R8:
9032                                 for (i = 0; i < alen; i++) {
9033                                         double val;
9034                                         readr8 (p, &val);
9035                                         mono_array_set (arr, double, i, val);
9036                                         p += 8;
9037                                 }
9038                                 break;
9039                         case MONO_TYPE_U8:
9040                         case MONO_TYPE_I8:
9041                                 for (i = 0; i < alen; i++) {
9042                                         guint64 val = read64 (p);
9043                                         mono_array_set (arr, guint64, i, val);
9044                                         p += 8;
9045                                 }
9046                                 break;
9047                         case MONO_TYPE_CLASS:
9048                         case MONO_TYPE_OBJECT:
9049                         case MONO_TYPE_STRING:
9050                         case MONO_TYPE_SZARRAY:
9051                                 for (i = 0; i < alen; i++) {
9052                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9053                                         if (!mono_error_ok (error))
9054                                                 return NULL;
9055                                         mono_array_setref (arr, i, item);
9056                                 }
9057                                 break;
9058                         default:
9059                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9060                 }
9061                 *end=p;
9062                 return arr;
9063         }
9064         default:
9065                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9066         }
9067         return NULL;
9068 }
9069
9070 static MonoObject*
9071 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9072 {
9073         static MonoMethod *ctor;
9074         MonoObject *retval;
9075         void *params [2], *unboxed;
9076
9077         mono_error_init (error);
9078
9079         if (!ctor)
9080                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9081         
9082         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9083         return_val_if_nok (error, NULL);
9084
9085         params [1] = val;
9086         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9087         return_val_if_nok (error, NULL);
9088         unboxed = mono_object_unbox (retval);
9089
9090         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9091         return_val_if_nok (error, NULL);
9092
9093         return retval;
9094 }
9095
9096 static MonoObject*
9097 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9098 {
9099         static MonoMethod *ctor;
9100         MonoObject *retval;
9101         void *unboxed, *params [2];
9102
9103         mono_error_init (error);
9104
9105         if (!ctor)
9106                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9107
9108         params [0] = minfo;
9109         params [1] = typedarg;
9110         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9111         return_val_if_nok (error, NULL);
9112
9113         unboxed = mono_object_unbox (retval);
9114
9115         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9116         return_val_if_nok (error, NULL);
9117
9118         return retval;
9119 }
9120
9121 static gboolean
9122 type_is_reference (MonoType *type)
9123 {
9124         switch (type->type) {
9125         case MONO_TYPE_BOOLEAN:
9126         case MONO_TYPE_CHAR:
9127         case MONO_TYPE_U:
9128         case MONO_TYPE_I:
9129         case MONO_TYPE_U1:
9130         case MONO_TYPE_I1:
9131         case MONO_TYPE_U2:
9132         case MONO_TYPE_I2:
9133         case MONO_TYPE_U4:
9134         case MONO_TYPE_I4:
9135         case MONO_TYPE_U8:
9136         case MONO_TYPE_I8:
9137         case MONO_TYPE_R8:
9138         case MONO_TYPE_R4:
9139         case MONO_TYPE_VALUETYPE:
9140                 return FALSE;
9141         default:
9142                 return TRUE;
9143         }
9144 }
9145
9146 static void
9147 free_param_data (MonoMethodSignature *sig, void **params) {
9148         int i;
9149         for (i = 0; i < sig->param_count; ++i) {
9150                 if (!type_is_reference (sig->params [i]))
9151                         g_free (params [i]);
9152         }
9153 }
9154
9155 /*
9156  * Find the field index in the metadata FieldDef table.
9157  */
9158 static guint32
9159 find_field_index (MonoClass *klass, MonoClassField *field) {
9160         int i;
9161
9162         for (i = 0; i < klass->field.count; ++i) {
9163                 if (field == &klass->fields [i])
9164                         return klass->field.first + 1 + i;
9165         }
9166         return 0;
9167 }
9168
9169 /*
9170  * Find the property index in the metadata Property table.
9171  */
9172 static guint32
9173 find_property_index (MonoClass *klass, MonoProperty *property) {
9174         int i;
9175
9176         for (i = 0; i < klass->ext->property.count; ++i) {
9177                 if (property == &klass->ext->properties [i])
9178                         return klass->ext->property.first + 1 + i;
9179         }
9180         return 0;
9181 }
9182
9183 /*
9184  * Find the event index in the metadata Event table.
9185  */
9186 static guint32
9187 find_event_index (MonoClass *klass, MonoEvent *event) {
9188         int i;
9189
9190         for (i = 0; i < klass->ext->event.count; ++i) {
9191                 if (event == &klass->ext->events [i])
9192                         return klass->ext->event.first + 1 + i;
9193         }
9194         return 0;
9195 }
9196
9197 static MonoObject*
9198 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9199 {
9200         const char *p = (const char*)data;
9201         const char *named;
9202         guint32 i, j, num_named;
9203         MonoObject *attr;
9204         void *params_buf [32];
9205         void **params = NULL;
9206         MonoMethodSignature *sig;
9207         MonoObject *exc = NULL;
9208
9209         mono_error_init (error);
9210
9211         mono_class_init (method->klass);
9212
9213         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9214                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9215                 return NULL;
9216         }
9217
9218         if (len == 0) {
9219                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9220                 if (!mono_error_ok (error)) return NULL;
9221
9222                 mono_runtime_invoke_checked (method, attr, NULL, error);
9223                 if (!mono_error_ok (error))
9224                         return NULL;
9225
9226                 return attr;
9227         }
9228
9229         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9230                 return NULL;
9231
9232         /*g_print ("got attr %s\n", method->klass->name);*/
9233
9234         sig = mono_method_signature (method);
9235         if (sig->param_count < 32) {
9236                 params = params_buf;
9237                 memset (params, 0, sizeof (void*) * sig->param_count);
9238         } else {
9239                 /* Allocate using GC so it gets GC tracking */
9240                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9241         }
9242
9243         /* skip prolog */
9244         p += 2;
9245         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9246                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9247                 if (!mono_error_ok (error))
9248                         goto fail;
9249         }
9250
9251         named = p;
9252         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9253         if (!mono_error_ok (error)) goto fail;
9254
9255         mono_runtime_try_invoke (method, attr, params, &exc, error);
9256         if (!mono_error_ok (error))
9257                 goto fail;
9258         if (exc)
9259                 goto fail;
9260
9261         num_named = read16 (named);
9262         named += 2;
9263         for (j = 0; j < num_named; j++) {
9264                 gint name_len;
9265                 char *name, named_type, data_type;
9266                 named_type = *named++;
9267                 data_type = *named++; /* type of data */
9268                 if (data_type == MONO_TYPE_SZARRAY)
9269                         data_type = *named++;
9270                 if (data_type == MONO_TYPE_ENUM) {
9271                         gint type_len;
9272                         char *type_name;
9273                         type_len = mono_metadata_decode_blob_size (named, &named);
9274                         type_name = (char *)g_malloc (type_len + 1);
9275                         memcpy (type_name, named, type_len);
9276                         type_name [type_len] = 0;
9277                         named += type_len;
9278                         /* FIXME: lookup the type and check type consistency */
9279                         g_free (type_name);
9280                 }
9281                 name_len = mono_metadata_decode_blob_size (named, &named);
9282                 name = (char *)g_malloc (name_len + 1);
9283                 memcpy (name, named, name_len);
9284                 name [name_len] = 0;
9285                 named += name_len;
9286                 if (named_type == 0x53) {
9287                         MonoClassField *field;
9288                         void *val;
9289
9290                         /* how this fail is a blackbox */
9291                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9292                         if (!field) {
9293                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9294                                 g_free (name);
9295                                 goto fail;
9296                         }
9297
9298                         val = load_cattr_value (image, field->type, named, &named, error);
9299                         if (!mono_error_ok (error)) {
9300                                 g_free (name);
9301                                 if (!type_is_reference (field->type))
9302                                         g_free (val);
9303                                 goto fail;
9304                         }
9305
9306                         mono_field_set_value (attr, field, val);
9307                         if (!type_is_reference (field->type))
9308                                 g_free (val);
9309                 } else if (named_type == 0x54) {
9310                         MonoProperty *prop;
9311                         void *pparams [1];
9312                         MonoType *prop_type;
9313
9314                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9315
9316                         if (!prop) {
9317                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9318                                 g_free (name);
9319                                 goto fail;
9320                         }
9321
9322                         if (!prop->set) {
9323                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9324                                 g_free (name);
9325                                 goto fail;
9326                         }
9327
9328                         /* can we have more that 1 arg in a custom attr named property? */
9329                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9330                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9331
9332                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9333                         if (!mono_error_ok (error)) {
9334                                 g_free (name);
9335                                 if (!type_is_reference (prop_type))
9336                                         g_free (pparams [0]);
9337                                 goto fail;
9338                         }
9339
9340
9341                         mono_property_set_value (prop, attr, pparams, NULL);
9342                         if (!type_is_reference (prop_type))
9343                                 g_free (pparams [0]);
9344                 }
9345                 g_free (name);
9346         }
9347
9348         free_param_data (method->signature, params);
9349         if (params != params_buf)
9350                 mono_gc_free_fixed (params);
9351
9352         return attr;
9353
9354 fail:
9355         free_param_data (method->signature, params);
9356         if (params != params_buf)
9357                 mono_gc_free_fixed (params);
9358         if (exc)
9359                 mono_raise_exception ((MonoException*)exc);
9360         return NULL;
9361 }
9362         
9363 /*
9364  * mono_reflection_create_custom_attr_data_args:
9365  *
9366  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9367  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9368  * NAMED_ARG_INFO will contain information about the named arguments.
9369  */
9370 void
9371 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)
9372 {
9373         MonoArray *typedargs, *namedargs;
9374         MonoClass *attrklass;
9375         MonoDomain *domain;
9376         const char *p = (const char*)data;
9377         const char *named;
9378         guint32 i, j, num_named;
9379         CattrNamedArg *arginfo = NULL;
9380
9381         *typed_args = NULL;
9382         *named_args = NULL;
9383         *named_arg_info = NULL;
9384
9385         mono_error_init (error);
9386
9387         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9388                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9389                 return;
9390         }
9391
9392         mono_class_init (method->klass);
9393         
9394         domain = mono_domain_get ();
9395
9396         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9397                 return;
9398
9399         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9400         
9401         /* skip prolog */
9402         p += 2;
9403         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9404                 MonoObject *obj;
9405                 void *val;
9406
9407                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9408                 if (!mono_error_ok (error)) {
9409                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9410                                 g_free (val);
9411                         return;
9412                 }
9413
9414                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9415                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9416                 mono_array_setref (typedargs, i, obj);
9417
9418                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9419                         g_free (val);
9420         }
9421
9422         named = p;
9423         num_named = read16 (named);
9424         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9425         named += 2;
9426         attrklass = method->klass;
9427
9428         arginfo = g_new0 (CattrNamedArg, num_named);
9429         *named_arg_info = arginfo;
9430
9431         for (j = 0; j < num_named; j++) {
9432                 gint name_len;
9433                 char *name, named_type, data_type;
9434                 named_type = *named++;
9435                 data_type = *named++; /* type of data */
9436                 if (data_type == MONO_TYPE_SZARRAY)
9437                         data_type = *named++;
9438                 if (data_type == MONO_TYPE_ENUM) {
9439                         gint type_len;
9440                         char *type_name;
9441                         type_len = mono_metadata_decode_blob_size (named, &named);
9442                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9443                                 goto fail;
9444
9445                         type_name = (char *)g_malloc (type_len + 1);
9446                         memcpy (type_name, named, type_len);
9447                         type_name [type_len] = 0;
9448                         named += type_len;
9449                         /* FIXME: lookup the type and check type consistency */
9450                         g_free (type_name);
9451                 }
9452                 name_len = mono_metadata_decode_blob_size (named, &named);
9453                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9454                         goto fail;
9455                 name = (char *)g_malloc (name_len + 1);
9456                 memcpy (name, named, name_len);
9457                 name [name_len] = 0;
9458                 named += name_len;
9459                 if (named_type == 0x53) {
9460                         MonoObject *obj;
9461                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9462                         void *val;
9463
9464                         if (!field) {
9465                                 g_free (name);
9466                                 goto fail;
9467                         }
9468
9469                         arginfo [j].type = field->type;
9470                         arginfo [j].field = field;
9471
9472                         val = load_cattr_value (image, field->type, named, &named, error);
9473                         if (!mono_error_ok (error)) {
9474                                 if (!type_is_reference (field->type))
9475                                         g_free (val);
9476                                 g_free (name);
9477                                 return;
9478                         }
9479
9480                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9481                         mono_array_setref (namedargs, j, obj);
9482                         if (!type_is_reference (field->type))
9483                                 g_free (val);
9484                 } else if (named_type == 0x54) {
9485                         MonoObject *obj;
9486                         MonoType *prop_type;
9487                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9488                         void *val;
9489
9490                         if (!prop || !prop->set) {
9491                                 g_free (name);
9492                                 goto fail;
9493                         }
9494
9495                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9496                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9497
9498                         arginfo [j].type = prop_type;
9499                         arginfo [j].prop = prop;
9500
9501                         val = load_cattr_value (image, prop_type, named, &named, error);
9502                         if (!mono_error_ok (error)) {
9503                                 if (!type_is_reference (prop_type))
9504                                         g_free (val);
9505                                 g_free (name);
9506                                 return;
9507                         }
9508
9509                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9510                         mono_array_setref (namedargs, j, obj);
9511                         if (!type_is_reference (prop_type))
9512                                 g_free (val);
9513                 }
9514                 g_free (name);
9515         }
9516
9517         *typed_args = typedargs;
9518         *named_args = namedargs;
9519         return;
9520 fail:
9521         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9522         g_free (arginfo);
9523         *named_arg_info = NULL;
9524 }
9525
9526 void
9527 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9528 {
9529         MonoDomain *domain;
9530         MonoArray *typedargs, *namedargs;
9531         MonoImage *image;
9532         MonoMethod *method;
9533         CattrNamedArg *arginfo = NULL;
9534         MonoError error;
9535         int i;
9536
9537         mono_error_init (&error);
9538
9539         *ctor_args = NULL;
9540         *named_args = NULL;
9541
9542         if (len == 0)
9543                 return;
9544
9545         image = assembly->assembly->image;
9546         method = ref_method->method;
9547         domain = mono_object_domain (ref_method);
9548
9549         if (!mono_class_init (method->klass))
9550                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9551
9552         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9553         if (!mono_error_ok (&error))
9554                 goto leave;
9555
9556         if (mono_loader_get_last_error ()) {
9557                 mono_error_set_from_loader_error (&error);
9558                 goto leave;
9559         }
9560
9561         if (!typedargs || !namedargs)
9562                 goto leave;
9563
9564         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9565                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9566                 MonoObject *typedarg;
9567
9568                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9569                 if (!is_ok (&error))
9570                         goto leave;
9571                 mono_array_setref (typedargs, i, typedarg);
9572         }
9573
9574         for (i = 0; i < mono_array_length (namedargs); ++i) {
9575                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9576                 MonoObject *typedarg, *namedarg, *minfo;
9577
9578                 if (arginfo [i].prop) {
9579                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9580                         if (!minfo)
9581                                 goto leave;
9582                 } else {
9583                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9584                         if (!mono_error_ok (&error))
9585                                 goto leave;
9586                 }
9587
9588                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9589                 if (!is_ok (&error))
9590                         goto leave;
9591                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9592                 if (!is_ok (&error))
9593                         goto leave;
9594
9595                 mono_array_setref (namedargs, i, namedarg);
9596         }
9597
9598         *ctor_args = typedargs;
9599         *named_args = namedargs;
9600 leave:
9601         g_free (arginfo);
9602         mono_error_raise_exception (&error);
9603
9604 }
9605
9606 static MonoObject*
9607 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9608 {
9609         static MonoMethod *ctor;
9610
9611         MonoDomain *domain;
9612         MonoObject *attr;
9613         void *params [4];
9614
9615         mono_error_init (error);
9616
9617         g_assert (image->assembly);
9618
9619         if (!ctor)
9620                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9621
9622         domain = mono_domain_get ();
9623         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9624         return_val_if_nok (error, NULL);
9625         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9626         return_val_if_nok (error, NULL);
9627         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9628         return_val_if_nok (error, NULL);
9629         params [2] = (gpointer)&cattr->data;
9630         params [3] = &cattr->data_size;
9631
9632         mono_runtime_invoke_checked (ctor, attr, params, error);
9633         return_val_if_nok (error, NULL);
9634         return attr;
9635 }
9636
9637 static MonoArray*
9638 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9639 {
9640         MonoArray *result;
9641         MonoObject *attr;
9642         int i, n;
9643
9644         mono_error_init (error);
9645
9646         n = 0;
9647         for (i = 0; i < cinfo->num_attrs; ++i) {
9648                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9649                         n ++;
9650         }
9651
9652         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9653         n = 0;
9654         for (i = 0; i < cinfo->num_attrs; ++i) {
9655                 if (!cinfo->attrs [i].ctor) {
9656                         /* The cattr type is not finished yet */
9657                         /* We should include the type name but cinfo doesn't contain it */
9658                         mono_error_set_type_load_name (error, NULL, NULL, "");
9659                         return NULL;
9660                 }
9661                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9662                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9663                         if (!mono_error_ok (error))
9664                                 return result;
9665                         mono_array_setref (result, n, attr);
9666                         n ++;
9667                 }
9668         }
9669         return result;
9670 }
9671
9672 MonoArray*
9673 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9674 {
9675         MonoError error;
9676         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9677         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9678
9679         return result;
9680 }
9681
9682 static MonoArray*
9683 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9684 {
9685         MonoArray *result;
9686         MonoObject *attr;
9687         int i;
9688         
9689         mono_error_init (error);
9690         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9691         for (i = 0; i < cinfo->num_attrs; ++i) {
9692                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9693                 return_val_if_nok (error, NULL);
9694                 mono_array_setref (result, i, attr);
9695         }
9696         return result;
9697 }
9698
9699 /**
9700  * mono_custom_attrs_from_index:
9701  *
9702  * Returns: NULL if no attributes are found or if a loading error occurs.
9703  */
9704 MonoCustomAttrInfo*
9705 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9706 {
9707         MonoError error;
9708         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9709         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9710         return result;
9711 }
9712 /**
9713  * mono_custom_attrs_from_index_checked:
9714  *
9715  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9716  */
9717 MonoCustomAttrInfo*
9718 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9719 {
9720         guint32 mtoken, i, len;
9721         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9722         MonoTableInfo *ca;
9723         MonoCustomAttrInfo *ainfo;
9724         GList *tmp, *list = NULL;
9725         const char *data;
9726         MonoCustomAttrEntry* attr;
9727
9728         mono_error_init (error);
9729
9730         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9731
9732         i = mono_metadata_custom_attrs_from_index (image, idx);
9733         if (!i)
9734                 return NULL;
9735         i --;
9736         while (i < ca->rows) {
9737                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9738                         break;
9739                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9740                 ++i;
9741         }
9742         len = g_list_length (list);
9743         if (!len)
9744                 return NULL;
9745         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9746         ainfo->num_attrs = len;
9747         ainfo->image = image;
9748         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9749                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9750                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9751                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9752                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9753                         mtoken |= MONO_TOKEN_METHOD_DEF;
9754                         break;
9755                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9756                         mtoken |= MONO_TOKEN_MEMBER_REF;
9757                         break;
9758                 default:
9759                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9760                         break;
9761                 }
9762                 attr = &ainfo->attrs [i - 1];
9763                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9764                 if (!attr->ctor) {
9765                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9766                         g_list_free (list);
9767                         g_free (ainfo);
9768                         return NULL;
9769                 }
9770
9771                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9772                         /*FIXME raising an exception here doesn't make any sense*/
9773                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9774                         g_list_free (list);
9775                         g_free (ainfo);
9776                         return NULL;
9777                 }
9778                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9779                 attr->data_size = mono_metadata_decode_value (data, &data);
9780                 attr->data = (guchar*)data;
9781         }
9782         g_list_free (list);
9783
9784         return ainfo;
9785 }
9786
9787 MonoCustomAttrInfo*
9788 mono_custom_attrs_from_method (MonoMethod *method)
9789 {
9790         MonoError error;
9791         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9792         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9793         return result;
9794 }
9795
9796 MonoCustomAttrInfo*
9797 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9798 {
9799         guint32 idx;
9800
9801         mono_error_init (error);
9802
9803         /*
9804          * An instantiated method has the same cattrs as the generic method definition.
9805          *
9806          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9807          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9808          */
9809         if (method->is_inflated)
9810                 method = ((MonoMethodInflated *) method)->declaring;
9811         
9812         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9813                 return lookup_custom_attr (method->klass->image, method);
9814
9815         if (!method->token)
9816                 /* Synthetic methods */
9817                 return NULL;
9818
9819         idx = mono_method_get_index (method);
9820         idx <<= MONO_CUSTOM_ATTR_BITS;
9821         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9822         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9823 }
9824
9825 MonoCustomAttrInfo*
9826 mono_custom_attrs_from_class (MonoClass *klass)
9827 {
9828         MonoError error;
9829         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9830         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9831         return result;
9832 }
9833
9834 MonoCustomAttrInfo*
9835 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9836 {
9837         guint32 idx;
9838
9839         mono_error_init (error);
9840
9841         if (klass->generic_class)
9842                 klass = klass->generic_class->container_class;
9843
9844         if (image_is_dynamic (klass->image))
9845                 return lookup_custom_attr (klass->image, klass);
9846
9847         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9848                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9849                 idx <<= MONO_CUSTOM_ATTR_BITS;
9850                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9851         } else {
9852                 idx = mono_metadata_token_index (klass->type_token);
9853                 idx <<= MONO_CUSTOM_ATTR_BITS;
9854                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9855         }
9856         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9857 }
9858
9859 MonoCustomAttrInfo*
9860 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9861 {
9862         MonoError error;
9863         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9864         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9865         return result;
9866 }
9867
9868 MonoCustomAttrInfo*
9869 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9870 {
9871         guint32 idx;
9872         
9873         mono_error_init (error);
9874
9875         if (image_is_dynamic (assembly->image))
9876                 return lookup_custom_attr (assembly->image, assembly);
9877         idx = 1; /* there is only one assembly */
9878         idx <<= MONO_CUSTOM_ATTR_BITS;
9879         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9880         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9881 }
9882
9883 static MonoCustomAttrInfo*
9884 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9885 {
9886         guint32 idx;
9887         
9888         if (image_is_dynamic (image))
9889                 return lookup_custom_attr (image, image);
9890         idx = 1; /* there is only one module */
9891         idx <<= MONO_CUSTOM_ATTR_BITS;
9892         idx |= MONO_CUSTOM_ATTR_MODULE;
9893         return mono_custom_attrs_from_index_checked (image, idx, error);
9894 }
9895
9896 MonoCustomAttrInfo*
9897 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9898 {
9899         MonoError error;
9900         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9901         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9902         return result;
9903 }
9904
9905 MonoCustomAttrInfo*
9906 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9907 {
9908         guint32 idx;
9909         
9910         if (image_is_dynamic (klass->image)) {
9911                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9912                 return lookup_custom_attr (klass->image, property);
9913         }
9914         idx = find_property_index (klass, property);
9915         idx <<= MONO_CUSTOM_ATTR_BITS;
9916         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9917         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9918 }
9919
9920 MonoCustomAttrInfo*
9921 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9922 {
9923         MonoError error;
9924         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9925         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9926         return result;
9927 }
9928
9929 MonoCustomAttrInfo*
9930 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9931 {
9932         guint32 idx;
9933         
9934         if (image_is_dynamic (klass->image)) {
9935                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9936                 return lookup_custom_attr (klass->image, event);
9937         }
9938         idx = find_event_index (klass, event);
9939         idx <<= MONO_CUSTOM_ATTR_BITS;
9940         idx |= MONO_CUSTOM_ATTR_EVENT;
9941         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9946 {
9947         MonoError error;
9948         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9949         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9950         return result;
9951 }
9952
9953 MonoCustomAttrInfo*
9954 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9955 {
9956         guint32 idx;
9957         mono_error_init (error);
9958
9959         if (image_is_dynamic (klass->image)) {
9960                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9961                 return lookup_custom_attr (klass->image, field);
9962         }
9963         idx = find_field_index (klass, field);
9964         idx <<= MONO_CUSTOM_ATTR_BITS;
9965         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9966         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9967 }
9968
9969 /**
9970  * mono_custom_attrs_from_param:
9971  * @method: handle to the method that we want to retrieve custom parameter information from
9972  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9973  *
9974  * The result must be released with mono_custom_attrs_free().
9975  *
9976  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9977  */
9978 MonoCustomAttrInfo*
9979 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9980 {
9981         MonoError error;
9982         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9983         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9984         return result;
9985 }
9986
9987 /**
9988  * mono_custom_attrs_from_param_checked:
9989  * @method: handle to the method that we want to retrieve custom parameter information from
9990  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9991  * @error: set on error
9992  *
9993  * The result must be released with mono_custom_attrs_free().
9994  *
9995  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
9996  */
9997 MonoCustomAttrInfo*
9998 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
9999 {
10000         MonoTableInfo *ca;
10001         guint32 i, idx, method_index;
10002         guint32 param_list, param_last, param_pos, found;
10003         MonoImage *image;
10004         MonoReflectionMethodAux *aux;
10005
10006         mono_error_init (error);
10007
10008         /*
10009          * An instantiated method has the same cattrs as the generic method definition.
10010          *
10011          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10012          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10013          */
10014         if (method->is_inflated)
10015                 method = ((MonoMethodInflated *) method)->declaring;
10016
10017         if (image_is_dynamic (method->klass->image)) {
10018                 MonoCustomAttrInfo *res, *ainfo;
10019                 int size;
10020
10021                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10022                 if (!aux || !aux->param_cattr)
10023                         return NULL;
10024
10025                 /* Need to copy since it will be freed later */
10026                 ainfo = aux->param_cattr [param];
10027                 if (!ainfo)
10028                         return NULL;
10029                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10030                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10031                 memcpy (res, ainfo, size);
10032                 return res;
10033         }
10034
10035         image = method->klass->image;
10036         method_index = mono_method_get_index (method);
10037         if (!method_index)
10038                 return NULL;
10039         ca = &image->tables [MONO_TABLE_METHOD];
10040
10041         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10042         if (method_index == ca->rows) {
10043                 ca = &image->tables [MONO_TABLE_PARAM];
10044                 param_last = ca->rows + 1;
10045         } else {
10046                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10047                 ca = &image->tables [MONO_TABLE_PARAM];
10048         }
10049         found = FALSE;
10050         for (i = param_list; i < param_last; ++i) {
10051                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10052                 if (param_pos == param) {
10053                         found = TRUE;
10054                         break;
10055                 }
10056         }
10057         if (!found)
10058                 return NULL;
10059         idx = i;
10060         idx <<= MONO_CUSTOM_ATTR_BITS;
10061         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10062         return mono_custom_attrs_from_index_checked (image, idx, error);
10063 }
10064
10065 gboolean
10066 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10067 {
10068         int i;
10069         MonoClass *klass;
10070         for (i = 0; i < ainfo->num_attrs; ++i) {
10071                 klass = ainfo->attrs [i].ctor->klass;
10072                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10073                         return TRUE;
10074         }
10075         return FALSE;
10076 }
10077
10078 MonoObject*
10079 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10080 {
10081         MonoError error;
10082         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10083         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10084         return res;
10085 }
10086
10087 MonoObject*
10088 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10089 {
10090         int i, attr_index;
10091         MonoClass *klass;
10092         MonoArray *attrs;
10093
10094         mono_error_init (error);
10095
10096         attr_index = -1;
10097         for (i = 0; i < ainfo->num_attrs; ++i) {
10098                 klass = ainfo->attrs [i].ctor->klass;
10099                 if (mono_class_has_parent (klass, attr_klass)) {
10100                         attr_index = i;
10101                         break;
10102                 }
10103         }
10104         if (attr_index == -1)
10105                 return NULL;
10106
10107         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10108         if (!mono_error_ok (error))
10109                 return NULL;
10110         return mono_array_get (attrs, MonoObject*, attr_index);
10111 }
10112
10113 /*
10114  * mono_reflection_get_custom_attrs_info:
10115  * @obj: a reflection object handle
10116  *
10117  * Return the custom attribute info for attributes defined for the
10118  * reflection handle @obj. The objects.
10119  *
10120  * FIXME this function leaks like a sieve for SRE objects.
10121  */
10122 MonoCustomAttrInfo*
10123 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10124 {
10125         MonoError error;
10126         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10127         mono_error_assert_ok (&error);
10128         return result;
10129 }
10130
10131 /**
10132  * mono_reflection_get_custom_attrs_info_checked:
10133  * @obj: a reflection object handle
10134  * @error: set on error
10135  *
10136  * Return the custom attribute info for attributes defined for the
10137  * reflection handle @obj. The objects.
10138  *
10139  * On failure returns NULL and sets @error.
10140  *
10141  * FIXME this function leaks like a sieve for SRE objects.
10142  */
10143 MonoCustomAttrInfo*
10144 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10145 {
10146         MonoClass *klass;
10147         MonoCustomAttrInfo *cinfo = NULL;
10148         
10149         mono_error_init (error);
10150
10151         klass = obj->vtable->klass;
10152         if (klass == mono_defaults.monotype_class) {
10153                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10154                 return_val_if_nok (error, NULL);
10155                 klass = mono_class_from_mono_type (type);
10156                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10157                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10158                 return_val_if_nok (error, NULL);
10159         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10160                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10161                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10162                 return_val_if_nok (error, NULL);
10163         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10164                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10165                 cinfo = mono_custom_attrs_from_module (module->image, error);
10166                 return_val_if_nok (error, NULL);
10167         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10168                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10169                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10170                 return_val_if_nok (error, NULL);
10171         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10172                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10173                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10174                 return_val_if_nok (error, NULL);
10175         } else if (strcmp ("MonoField", klass->name) == 0) {
10176                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10177                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10178                 return_val_if_nok (error, NULL);
10179         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10180                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10181                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10182                 return_val_if_nok (error, NULL);
10183         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10184                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10185                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10186                 return_val_if_nok (error, NULL);
10187         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10188                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10189                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10190                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10191                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10192                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10193                         return_val_if_nok (error, NULL);
10194                 } else if (is_sr_mono_property (member_class)) {
10195                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10196                         MonoMethod *method;
10197                         if (!(method = prop->property->get))
10198                                 method = prop->property->set;
10199                         g_assert (method);
10200
10201                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10202                         return_val_if_nok (error, NULL);
10203                 } 
10204 #ifndef DISABLE_REFLECTION_EMIT
10205                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10206                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10207                         return_val_if_nok (error, NULL);
10208                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10209                         return_val_if_nok (error, NULL);
10210                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10211                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10212                         MonoMethod *method = NULL;
10213                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10214                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10215                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10216                                 method = ((MonoReflectionMethod *)c->cb)->method;
10217                         else
10218                                 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));
10219
10220                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10221                         return_val_if_nok (error, NULL);
10222                 } 
10223 #endif
10224                 else {
10225                         char *type_name = mono_type_get_full_name (member_class);
10226                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10227                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10228                                                       type_name);
10229                         g_free (type_name);
10230                         return NULL;
10231                 }
10232         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10233                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10234                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10235         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10236                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10237                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10238         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10239                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10240                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10241         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10242                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10243                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10244         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10245                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10246                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10247         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10248                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10249                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10250         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10251                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10252                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10253                 return_val_if_nok (error, NULL);
10254         } else { /* handle other types here... */
10255                 g_error ("get custom attrs not yet supported for %s", klass->name);
10256         }
10257
10258         return cinfo;
10259 }
10260
10261 /*
10262  * mono_reflection_get_custom_attrs_by_type:
10263  * @obj: a reflection object handle
10264  *
10265  * Return an array with all the custom attributes defined of the
10266  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10267  * of that type are returned. The objects are fully build. Return NULL if a loading error
10268  * occurs.
10269  */
10270 MonoArray*
10271 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10272 {
10273         MonoArray *result;
10274         MonoCustomAttrInfo *cinfo;
10275
10276         mono_error_init (error);
10277
10278         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10279         return_val_if_nok (error, NULL);
10280         if (cinfo) {
10281                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10282                 if (!result)
10283                         return NULL;
10284                 if (!cinfo->cached)
10285                         mono_custom_attrs_free (cinfo);
10286         } else {
10287                 mono_loader_assert_no_error ();
10288                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10289         }
10290
10291         return result;
10292 }
10293
10294 /*
10295  * mono_reflection_get_custom_attrs:
10296  * @obj: a reflection object handle
10297  *
10298  * Return an array with all the custom attributes defined of the
10299  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10300  * occurs.
10301  */
10302 MonoArray*
10303 mono_reflection_get_custom_attrs (MonoObject *obj)
10304 {
10305         MonoError error;
10306
10307         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10308 }
10309
10310 /*
10311  * mono_reflection_get_custom_attrs_data:
10312  * @obj: a reflection obj handle
10313  *
10314  * Returns an array of System.Reflection.CustomAttributeData,
10315  * which include information about attributes reflected on
10316  * types loaded using the Reflection Only methods
10317  */
10318 MonoArray*
10319 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10320 {
10321         MonoError error;
10322         MonoArray* result;
10323         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10324         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10325         return result;
10326 }
10327
10328 /*
10329  * mono_reflection_get_custom_attrs_data_checked:
10330  * @obj: a reflection obj handle
10331  * @error: set on error
10332  *
10333  * Returns an array of System.Reflection.CustomAttributeData,
10334  * which include information about attributes reflected on
10335  * types loaded using the Reflection Only methods
10336  */
10337 MonoArray*
10338 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10339 {
10340         MonoArray *result;
10341         MonoCustomAttrInfo *cinfo;
10342
10343         mono_error_init (error);
10344
10345         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10346         return_val_if_nok (error, NULL);
10347         if (cinfo) {
10348                 result = mono_custom_attrs_data_construct (cinfo, error);
10349                 return_val_if_nok (error, NULL);
10350                 if (!cinfo->cached)
10351                         mono_custom_attrs_free (cinfo);
10352         } else
10353                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10354
10355         if (mono_loader_get_last_error ())
10356                 mono_error_set_from_loader_error (error);
10357
10358         return result;
10359 }
10360
10361 static MonoReflectionType*
10362 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10363 {
10364         static MonoMethod *method_get_underlying_system_type = NULL;
10365         MonoReflectionType *rt;
10366         MonoMethod *usertype_method;
10367
10368         mono_error_init (error);
10369
10370         if (!method_get_underlying_system_type)
10371                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10372
10373         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10374
10375         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10376
10377         return rt;
10378 }
10379
10380
10381 static gboolean
10382 is_corlib_type (MonoClass *klass)
10383 {
10384         return klass->image == mono_defaults.corlib;
10385 }
10386
10387 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10388         static MonoClass *cached_class; \
10389         if (cached_class) \
10390                 return cached_class == _class; \
10391         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10392                 cached_class = _class; \
10393                 return TRUE; \
10394         } \
10395         return FALSE; \
10396 } while (0) \
10397
10398
10399 #ifndef DISABLE_REFLECTION_EMIT
10400 static gboolean
10401 is_sre_array (MonoClass *klass)
10402 {
10403         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10404 }
10405
10406 static gboolean
10407 is_sre_byref (MonoClass *klass)
10408 {
10409         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10410 }
10411
10412 static gboolean
10413 is_sre_pointer (MonoClass *klass)
10414 {
10415         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10416 }
10417
10418 static gboolean
10419 is_sre_generic_instance (MonoClass *klass)
10420 {
10421         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10422 }
10423
10424 static gboolean
10425 is_sre_type_builder (MonoClass *klass)
10426 {
10427         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10428 }
10429
10430 static gboolean
10431 is_sre_method_builder (MonoClass *klass)
10432 {
10433         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10434 }
10435
10436 static gboolean
10437 is_sre_ctor_builder (MonoClass *klass)
10438 {
10439         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10440 }
10441
10442 static gboolean
10443 is_sre_field_builder (MonoClass *klass)
10444 {
10445         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10446 }
10447
10448 static gboolean
10449 is_sre_method_on_tb_inst (MonoClass *klass)
10450 {
10451         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10452 }
10453
10454 static gboolean
10455 is_sre_ctor_on_tb_inst (MonoClass *klass)
10456 {
10457         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10458 }
10459
10460 MonoType*
10461 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10462 {
10463         MonoClass *klass;
10464         mono_error_init (error);
10465
10466         if (!ref)
10467                 return NULL;
10468         if (ref->type)
10469                 return ref->type;
10470
10471         if (is_usertype (ref)) {
10472                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10473                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10474                         return NULL;
10475                 if (ref->type)
10476                         return ref->type;
10477         }
10478
10479         klass = mono_object_class (ref);
10480
10481         if (is_sre_array (klass)) {
10482                 MonoType *res;
10483                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10484                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10485                 return_val_if_nok (error, NULL);
10486                 g_assert (base);
10487                 if (sre_array->rank == 0) //single dimentional array
10488                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10489                 else
10490                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10491                 sre_array->type.type = res;
10492                 return res;
10493         } else if (is_sre_byref (klass)) {
10494                 MonoType *res;
10495                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10496                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10497                 return_val_if_nok (error, NULL);
10498                 g_assert (base);
10499                 res = &mono_class_from_mono_type (base)->this_arg;
10500                 sre_byref->type.type = res;
10501                 return res;
10502         } else if (is_sre_pointer (klass)) {
10503                 MonoType *res;
10504                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10505                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10506                 return_val_if_nok (error, NULL);
10507                 g_assert (base);
10508                 res = &mono_ptr_class_get (base)->byval_arg;
10509                 sre_pointer->type.type = res;
10510                 return res;
10511         } else if (is_sre_generic_instance (klass)) {
10512                 MonoType *res, **types;
10513                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10514                 int i, count;
10515
10516                 count = mono_array_length (gclass->type_arguments);
10517                 types = g_new0 (MonoType*, count);
10518                 for (i = 0; i < count; ++i) {
10519                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10520                         types [i] = mono_reflection_type_get_handle (t, error);
10521                         if (!types[i] || !is_ok (error)) {
10522                                 g_free (types);
10523                                 return NULL;
10524                         }
10525                 }
10526
10527                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10528                 g_free (types);
10529                 g_assert (res);
10530                 gclass->type.type = res;
10531                 return res;
10532         }
10533
10534         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10535         return NULL;
10536 }
10537
10538 void
10539 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10540 {
10541         MonoError error;
10542         mono_reflection_type_get_handle (type, &error);
10543         mono_error_set_pending_exception (&error);
10544 }
10545
10546 void
10547 mono_reflection_register_with_runtime (MonoReflectionType *type)
10548 {
10549         MonoError error;
10550         MonoType *res = mono_reflection_type_get_handle (type, &error);
10551         mono_error_raise_exception (&error); /* FIXME don't raise here */
10552         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10553         MonoClass *klass;
10554
10555         if (!res)
10556                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10557
10558         klass = mono_class_from_mono_type (res);
10559
10560         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10561         mono_domain_lock (domain);
10562
10563         if (!image_is_dynamic (klass->image)) {
10564                 mono_class_setup_supertypes (klass);
10565         } else {
10566                 if (!domain->type_hash)
10567                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10568                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10569                 mono_g_hash_table_insert (domain->type_hash, res, type);
10570         }
10571         mono_domain_unlock (domain);
10572         mono_loader_unlock ();
10573 }
10574
10575 /**
10576  * LOCKING: Assumes the loader lock is held.
10577  */
10578 static MonoMethodSignature*
10579 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10580         MonoError error;
10581         MonoMethodSignature *sig;
10582         int count, i;
10583
10584         count = parameters? mono_array_length (parameters): 0;
10585
10586         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10587         sig->param_count = count;
10588         sig->sentinelpos = -1; /* FIXME */
10589         for (i = 0; i < count; ++i) {
10590                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10591                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10592         }
10593         return sig;
10594 }
10595
10596 /**
10597  * LOCKING: Assumes the loader lock is held.
10598  */
10599 static MonoMethodSignature*
10600 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10601         MonoMethodSignature *sig;
10602
10603         sig = parameters_to_signature (image, ctor->parameters);
10604         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10605         sig->ret = &mono_defaults.void_class->byval_arg;
10606         return sig;
10607 }
10608
10609 /**
10610  * LOCKING: Assumes the loader lock is held.
10611  */
10612 static MonoMethodSignature*
10613 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10614         MonoError error;
10615         MonoMethodSignature *sig;
10616
10617         sig = parameters_to_signature (image, method->parameters);
10618         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10619         if (method->rtype) {
10620                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10621                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10622         } else {
10623                 sig->ret = &mono_defaults.void_class->byval_arg;
10624         }
10625         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10626         return sig;
10627 }
10628
10629 static MonoMethodSignature*
10630 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10631         MonoError error;
10632         MonoMethodSignature *sig;
10633
10634         sig = parameters_to_signature (NULL, method->parameters);
10635         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10636         if (method->rtype) {
10637                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10638                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10639         } else {
10640                 sig->ret = &mono_defaults.void_class->byval_arg;
10641         }
10642         sig->generic_param_count = 0;
10643         return sig;
10644 }
10645
10646 static void
10647 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10648 {
10649         MonoError error;
10650         MonoClass *klass = mono_object_class (prop);
10651         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10652                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10653                 *name = mono_string_to_utf8 (pb->name);
10654                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10655                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10656         } else {
10657                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10658                 *name = g_strdup (p->property->name);
10659                 if (p->property->get)
10660                         *type = mono_method_signature (p->property->get)->ret;
10661                 else
10662                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10663         }
10664 }
10665
10666 static void
10667 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10668 {
10669         MonoError error;
10670         MonoClass *klass = mono_object_class (field);
10671         if (strcmp (klass->name, "FieldBuilder") == 0) {
10672                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10673                 *name = mono_string_to_utf8 (fb->name);
10674                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10675                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10676         } else {
10677                 MonoReflectionField *f = (MonoReflectionField *)field;
10678                 *name = g_strdup (mono_field_get_name (f->field));
10679                 *type = f->field->type;
10680         }
10681 }
10682
10683 #else /* DISABLE_REFLECTION_EMIT */
10684
10685 void
10686 mono_reflection_register_with_runtime (MonoReflectionType *type)
10687 {
10688         /* This is empty */
10689 }
10690
10691 static gboolean
10692 is_sre_type_builder (MonoClass *klass)
10693 {
10694         return FALSE;
10695 }
10696
10697 static gboolean
10698 is_sre_generic_instance (MonoClass *klass)
10699 {
10700         return FALSE;
10701 }
10702
10703 static void
10704 init_type_builder_generics (MonoObject *type)
10705 {
10706 }
10707
10708 #endif /* !DISABLE_REFLECTION_EMIT */
10709
10710
10711 static gboolean
10712 is_sr_mono_field (MonoClass *klass)
10713 {
10714         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10715 }
10716
10717 static gboolean
10718 is_sr_mono_property (MonoClass *klass)
10719 {
10720         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10721 }
10722
10723 static gboolean
10724 is_sr_mono_method (MonoClass *klass)
10725 {
10726         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10727 }
10728
10729 static gboolean
10730 is_sr_mono_cmethod (MonoClass *klass)
10731 {
10732         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10733 }
10734
10735 static gboolean
10736 is_sr_mono_generic_method (MonoClass *klass)
10737 {
10738         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10739 }
10740
10741 static gboolean
10742 is_sr_mono_generic_cmethod (MonoClass *klass)
10743 {
10744         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10745 }
10746
10747 gboolean
10748 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10749 {
10750         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10751 }
10752
10753 static gboolean
10754 is_usertype (MonoReflectionType *ref)
10755 {
10756         MonoClass *klass = mono_object_class (ref);
10757         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10758 }
10759
10760 static MonoReflectionType*
10761 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10762 {
10763         mono_error_init (error);
10764         if (!type || type->type)
10765                 return type;
10766
10767         if (is_usertype (type)) {
10768                 type = mono_reflection_type_get_underlying_system_type (type, error);
10769                 return_val_if_nok (error, NULL);
10770                 if (is_usertype (type)) {
10771                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10772                         return NULL;
10773                 }
10774         }
10775
10776         return type;
10777 }
10778 /*
10779  * Encode a value in a custom attribute stream of bytes.
10780  * The value to encode is either supplied as an object in argument val
10781  * (valuetypes are boxed), or as a pointer to the data in the
10782  * argument argval.
10783  * @type represents the type of the value
10784  * @buffer is the start of the buffer
10785  * @p the current position in the buffer
10786  * @buflen contains the size of the buffer and is used to return the new buffer size
10787  * if this needs to be realloced.
10788  * @retbuffer and @retp return the start and the position of the buffer
10789  */
10790 static void
10791 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10792 {
10793         MonoError error;
10794         MonoTypeEnum simple_type;
10795         
10796         if ((p-buffer) + 10 >= *buflen) {
10797                 char *newbuf;
10798                 *buflen *= 2;
10799                 newbuf = (char *)g_realloc (buffer, *buflen);
10800                 p = newbuf + (p-buffer);
10801                 buffer = newbuf;
10802         }
10803         if (!argval)
10804                 argval = ((char*)arg + sizeof (MonoObject));
10805         simple_type = type->type;
10806 handle_enum:
10807         switch (simple_type) {
10808         case MONO_TYPE_BOOLEAN:
10809         case MONO_TYPE_U1:
10810         case MONO_TYPE_I1:
10811                 *p++ = *argval;
10812                 break;
10813         case MONO_TYPE_CHAR:
10814         case MONO_TYPE_U2:
10815         case MONO_TYPE_I2:
10816                 swap_with_size (p, argval, 2, 1);
10817                 p += 2;
10818                 break;
10819         case MONO_TYPE_U4:
10820         case MONO_TYPE_I4:
10821         case MONO_TYPE_R4:
10822                 swap_with_size (p, argval, 4, 1);
10823                 p += 4;
10824                 break;
10825         case MONO_TYPE_R8:
10826                 swap_with_size (p, argval, 8, 1);
10827                 p += 8;
10828                 break;
10829         case MONO_TYPE_U8:
10830         case MONO_TYPE_I8:
10831                 swap_with_size (p, argval, 8, 1);
10832                 p += 8;
10833                 break;
10834         case MONO_TYPE_VALUETYPE:
10835                 if (type->data.klass->enumtype) {
10836                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10837                         goto handle_enum;
10838                 } else {
10839                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10840                 }
10841                 break;
10842         case MONO_TYPE_STRING: {
10843                 char *str;
10844                 guint32 slen;
10845                 if (!arg) {
10846                         *p++ = 0xFF;
10847                         break;
10848                 }
10849                 str = mono_string_to_utf8 ((MonoString*)arg);
10850                 slen = strlen (str);
10851                 if ((p-buffer) + 10 + slen >= *buflen) {
10852                         char *newbuf;
10853                         *buflen *= 2;
10854                         *buflen += slen;
10855                         newbuf = (char *)g_realloc (buffer, *buflen);
10856                         p = newbuf + (p-buffer);
10857                         buffer = newbuf;
10858                 }
10859                 mono_metadata_encode_value (slen, p, &p);
10860                 memcpy (p, str, slen);
10861                 p += slen;
10862                 g_free (str);
10863                 break;
10864         }
10865         case MONO_TYPE_CLASS: {
10866                 char *str;
10867                 guint32 slen;
10868                 MonoType *arg_type;
10869                 if (!arg) {
10870                         *p++ = 0xFF;
10871                         break;
10872                 }
10873 handle_type:
10874                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10875                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10876                 str = type_get_qualified_name (arg_type, NULL);
10877                 slen = strlen (str);
10878                 if ((p-buffer) + 10 + slen >= *buflen) {
10879                         char *newbuf;
10880                         *buflen *= 2;
10881                         *buflen += slen;
10882                         newbuf = (char *)g_realloc (buffer, *buflen);
10883                         p = newbuf + (p-buffer);
10884                         buffer = newbuf;
10885                 }
10886                 mono_metadata_encode_value (slen, p, &p);
10887                 memcpy (p, str, slen);
10888                 p += slen;
10889                 g_free (str);
10890                 break;
10891         }
10892         case MONO_TYPE_SZARRAY: {
10893                 int len, i;
10894                 MonoClass *eclass, *arg_eclass;
10895
10896                 if (!arg) {
10897                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10898                         break;
10899                 }
10900                 len = mono_array_length ((MonoArray*)arg);
10901                 *p++ = len & 0xff;
10902                 *p++ = (len >> 8) & 0xff;
10903                 *p++ = (len >> 16) & 0xff;
10904                 *p++ = (len >> 24) & 0xff;
10905                 *retp = p;
10906                 *retbuffer = buffer;
10907                 eclass = type->data.klass;
10908                 arg_eclass = mono_object_class (arg)->element_class;
10909
10910                 if (!eclass) {
10911                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10912                         eclass = mono_defaults.object_class;
10913                 }
10914                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10915                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10916                         int elsize = mono_class_array_element_size (arg_eclass);
10917                         for (i = 0; i < len; ++i) {
10918                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10919                                 elptr += elsize;
10920                         }
10921                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10922                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10923                         int elsize = mono_class_array_element_size (eclass);
10924                         for (i = 0; i < len; ++i) {
10925                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10926                                 elptr += elsize;
10927                         }
10928                 } else {
10929                         for (i = 0; i < len; ++i) {
10930                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10931                         }
10932                 }
10933                 break;
10934         }
10935         case MONO_TYPE_OBJECT: {
10936                 MonoClass *klass;
10937                 char *str;
10938                 guint32 slen;
10939
10940                 /*
10941                  * The parameter type is 'object' but the type of the actual
10942                  * argument is not. So we have to add type information to the blob
10943                  * too. This is completely undocumented in the spec.
10944                  */
10945
10946                 if (arg == NULL) {
10947                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10948                         *p++ = 0xFF;
10949                         break;
10950                 }
10951                 
10952                 klass = mono_object_class (arg);
10953
10954                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10955                         *p++ = 0x50;
10956                         goto handle_type;
10957                 } else if (klass->enumtype) {
10958                         *p++ = 0x55;
10959                 } else if (klass == mono_defaults.string_class) {
10960                         simple_type = MONO_TYPE_STRING;
10961                         *p++ = 0x0E;
10962                         goto handle_enum;
10963                 } else if (klass->rank == 1) {
10964                         *p++ = 0x1D;
10965                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10966                                 /* See Partition II, Appendix B3 */
10967                                 *p++ = 0x51;
10968                         else
10969                                 *p++ = klass->element_class->byval_arg.type;
10970                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10971                         break;
10972                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10973                         *p++ = simple_type = klass->byval_arg.type;
10974                         goto handle_enum;
10975                 } else {
10976                         g_error ("unhandled type in custom attr");
10977                 }
10978                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10979                 slen = strlen (str);
10980                 if ((p-buffer) + 10 + slen >= *buflen) {
10981                         char *newbuf;
10982                         *buflen *= 2;
10983                         *buflen += slen;
10984                         newbuf = (char *)g_realloc (buffer, *buflen);
10985                         p = newbuf + (p-buffer);
10986                         buffer = newbuf;
10987                 }
10988                 mono_metadata_encode_value (slen, p, &p);
10989                 memcpy (p, str, slen);
10990                 p += slen;
10991                 g_free (str);
10992                 simple_type = mono_class_enum_basetype (klass)->type;
10993                 goto handle_enum;
10994         }
10995         default:
10996                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10997         }
10998         *retp = p;
10999         *retbuffer = buffer;
11000 }
11001
11002 static void
11003 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11004 {
11005         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11006                 char *str = type_get_qualified_name (type, NULL);
11007                 int slen = strlen (str);
11008
11009                 *p++ = 0x55;
11010                 /*
11011                  * This seems to be optional...
11012                  * *p++ = 0x80;
11013                  */
11014                 mono_metadata_encode_value (slen, p, &p);
11015                 memcpy (p, str, slen);
11016                 p += slen;
11017                 g_free (str);
11018         } else if (type->type == MONO_TYPE_OBJECT) {
11019                 *p++ = 0x51;
11020         } else if (type->type == MONO_TYPE_CLASS) {
11021                 /* it should be a type: encode_cattr_value () has the check */
11022                 *p++ = 0x50;
11023         } else {
11024                 mono_metadata_encode_value (type->type, p, &p);
11025                 if (type->type == MONO_TYPE_SZARRAY)
11026                         /* See the examples in Partition VI, Annex B */
11027                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11028         }
11029
11030         *retp = p;
11031 }
11032
11033 #ifndef DISABLE_REFLECTION_EMIT
11034 static void
11035 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11036 {
11037         int len;
11038         /* Preallocate a large enough buffer */
11039         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11040                 char *str = type_get_qualified_name (type, NULL);
11041                 len = strlen (str);
11042                 g_free (str);
11043         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11044                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11045                 len = strlen (str);
11046                 g_free (str);
11047         } else {
11048                 len = 0;
11049         }
11050         len += strlen (name);
11051
11052         if ((p-buffer) + 20 + len >= *buflen) {
11053                 char *newbuf;
11054                 *buflen *= 2;
11055                 *buflen += len;
11056                 newbuf = (char *)g_realloc (buffer, *buflen);
11057                 p = newbuf + (p-buffer);
11058                 buffer = newbuf;
11059         }
11060
11061         encode_field_or_prop_type (type, p, &p);
11062
11063         len = strlen (name);
11064         mono_metadata_encode_value (len, p, &p);
11065         memcpy (p, name, len);
11066         p += len;
11067         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11068         *retp = p;
11069         *retbuffer = buffer;
11070 }
11071
11072 /*
11073  * mono_reflection_get_custom_attrs_blob:
11074  * @ctor: custom attribute constructor
11075  * @ctorArgs: arguments o the constructor
11076  * @properties:
11077  * @propValues:
11078  * @fields:
11079  * @fieldValues:
11080  * 
11081  * Creates the blob of data that needs to be saved in the metadata and that represents
11082  * the custom attributed described by @ctor, @ctorArgs etc.
11083  * Returns: a Byte array representing the blob of data.
11084  */
11085 MonoArray*
11086 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11087 {
11088         MonoArray *result;
11089         MonoMethodSignature *sig;
11090         MonoObject *arg;
11091         char *buffer, *p;
11092         guint32 buflen, i;
11093
11094         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11095                 /* sig is freed later so allocate it in the heap */
11096                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11097         } else {
11098                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11099         }
11100
11101         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11102         buflen = 256;
11103         p = buffer = (char *)g_malloc (buflen);
11104         /* write the prolog */
11105         *p++ = 1;
11106         *p++ = 0;
11107         for (i = 0; i < sig->param_count; ++i) {
11108                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11109                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11110         }
11111         i = 0;
11112         if (properties)
11113                 i += mono_array_length (properties);
11114         if (fields)
11115                 i += mono_array_length (fields);
11116         *p++ = i & 0xff;
11117         *p++ = (i >> 8) & 0xff;
11118         if (properties) {
11119                 MonoObject *prop;
11120                 for (i = 0; i < mono_array_length (properties); ++i) {
11121                         MonoType *ptype;
11122                         char *pname;
11123
11124                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11125                         get_prop_name_and_type (prop, &pname, &ptype);
11126                         *p++ = 0x54; /* PROPERTY signature */
11127                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11128                         g_free (pname);
11129                 }
11130         }
11131
11132         if (fields) {
11133                 MonoObject *field;
11134                 for (i = 0; i < mono_array_length (fields); ++i) {
11135                         MonoType *ftype;
11136                         char *fname;
11137
11138                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11139                         get_field_name_and_type (field, &fname, &ftype);
11140                         *p++ = 0x53; /* FIELD signature */
11141                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11142                         g_free (fname);
11143                 }
11144         }
11145
11146         g_assert (p - buffer <= buflen);
11147         buflen = p - buffer;
11148         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11149         p = mono_array_addr (result, char, 0);
11150         memcpy (p, buffer, buflen);
11151         g_free (buffer);
11152         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11153                 g_free (sig);
11154         return result;
11155 }
11156
11157 /*
11158  * mono_reflection_setup_internal_class:
11159  * @tb: a TypeBuilder object
11160  *
11161  * Creates a MonoClass that represents the TypeBuilder.
11162  * This is a trick that lets us simplify a lot of reflection code
11163  * (and will allow us to support Build and Run assemblies easier).
11164  */
11165 void
11166 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11167 {
11168         MonoError error;
11169         MonoClass *klass, *parent;
11170
11171         RESOLVE_TYPE (tb->parent, &error);
11172         mono_error_raise_exception (&error); /* FIXME don't raise here */
11173
11174         mono_loader_lock ();
11175
11176         if (tb->parent) {
11177                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11178                 if (!is_ok (&error)) {
11179                         mono_loader_unlock ();
11180                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11181                 }
11182                 /* check so we can compile corlib correctly */
11183                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11184                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11185                         parent = parent_type->data.klass;
11186                 } else {
11187                         parent = mono_class_from_mono_type (parent_type);
11188                 }
11189         } else {
11190                 parent = NULL;
11191         }
11192         
11193         /* the type has already being created: it means we just have to change the parent */
11194         if (tb->type.type) {
11195                 klass = mono_class_from_mono_type (tb->type.type);
11196                 klass->parent = NULL;
11197                 /* fool mono_class_setup_parent */
11198                 klass->supertypes = NULL;
11199                 mono_class_setup_parent (klass, parent);
11200                 mono_class_setup_mono_type (klass);
11201                 mono_loader_unlock ();
11202                 return;
11203         }
11204
11205         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11206
11207         klass->image = &tb->module->dynamic_image->image;
11208
11209         klass->inited = 1; /* we lie to the runtime */
11210         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11211         if (!mono_error_ok (&error))
11212                 goto failure;
11213         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11214         if (!mono_error_ok (&error))
11215                 goto failure;
11216         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11217         klass->flags = tb->attrs;
11218         
11219         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11220
11221         klass->element_class = klass;
11222
11223         if (mono_class_get_ref_info (klass) == NULL) {
11224
11225                 mono_class_set_ref_info (klass, tb);
11226
11227                 /* Put into cache so mono_class_get_checked () will find it.
11228                 Skip nested types as those should not be available on the global scope. */
11229                 if (!tb->nesting_type)
11230                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11231
11232                 /*
11233                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11234                 by performing a mono_class_get which does the full resolution.
11235
11236                 Working around this semantics would require us to write a lot of code for no clear advantage.
11237                 */
11238                 mono_image_append_class_to_reflection_info_set (klass);
11239         } else {
11240                 g_assert (mono_class_get_ref_info (klass) == tb);
11241         }
11242
11243         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11244
11245         if (parent != NULL) {
11246                 mono_class_setup_parent (klass, parent);
11247         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11248                 const char *old_n = klass->name;
11249                 /* trick to get relative numbering right when compiling corlib */
11250                 klass->name = "BuildingObject";
11251                 mono_class_setup_parent (klass, mono_defaults.object_class);
11252                 klass->name = old_n;
11253         }
11254
11255         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11256                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11257                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11258                 klass->instance_size = sizeof (MonoObject);
11259                 klass->size_inited = 1;
11260                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11261         }
11262
11263         mono_class_setup_mono_type (klass);
11264
11265         mono_class_setup_supertypes (klass);
11266
11267         /*
11268          * FIXME: handle interfaces.
11269          */
11270
11271         tb->type.type = &klass->byval_arg;
11272
11273         if (tb->nesting_type) {
11274                 g_assert (tb->nesting_type->type);
11275                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11276                 if (!is_ok (&error)) goto failure;
11277                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11278         }
11279
11280         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11281
11282         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11283         
11284         mono_loader_unlock ();
11285         return;
11286
11287 failure:
11288         mono_loader_unlock ();
11289         mono_error_raise_exception (&error);
11290 }
11291
11292 /*
11293  * mono_reflection_setup_generic_class:
11294  * @tb: a TypeBuilder object
11295  *
11296  * Setup the generic class before adding the first generic parameter.
11297  */
11298 void
11299 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11300 {
11301 }
11302
11303 /*
11304  * mono_reflection_create_generic_class:
11305  * @tb: a TypeBuilder object
11306  *
11307  * Creates the generic class after all generic parameters have been added.
11308  */
11309 void
11310 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11311 {
11312         MonoError error;
11313         MonoClass *klass;
11314         int count, i;
11315
11316         klass = mono_class_from_mono_type (tb->type.type);
11317
11318         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11319
11320         if (klass->generic_container || (count == 0))
11321                 return;
11322
11323         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11324
11325         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11326
11327         klass->generic_container->owner.klass = klass;
11328         klass->generic_container->type_argc = count;
11329         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11330
11331         klass->is_generic = 1;
11332
11333         for (i = 0; i < count; i++) {
11334                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11335                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11336                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11337                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11338                 klass->generic_container->type_params [i] = *param;
11339                 /*Make sure we are a diferent type instance */
11340                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11341                 klass->generic_container->type_params [i].info.pklass = NULL;
11342                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11343
11344                 g_assert (klass->generic_container->type_params [i].param.owner);
11345         }
11346
11347         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11348 }
11349
11350 /*
11351  * mono_reflection_create_internal_class:
11352  * @tb: a TypeBuilder object
11353  *
11354  * Actually create the MonoClass that is associated with the TypeBuilder.
11355  */
11356 void
11357 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11358 {
11359         MonoError error;
11360         MonoClass *klass;
11361
11362         klass = mono_class_from_mono_type (tb->type.type);
11363
11364         mono_loader_lock ();
11365         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11366                 MonoReflectionFieldBuilder *fb;
11367                 MonoClass *ec;
11368                 MonoType *enum_basetype;
11369
11370                 g_assert (tb->fields != NULL);
11371                 g_assert (mono_array_length (tb->fields) >= 1);
11372
11373                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11374
11375                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11376                 if (!is_ok (&error)) {
11377                         mono_loader_unlock ();
11378                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11379                 }
11380                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11381                         mono_loader_unlock ();
11382                         return;
11383                 }
11384
11385                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11386                 if (!is_ok (&error)) {
11387                         mono_loader_unlock ();
11388                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11389                 }
11390                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11391                 if (!klass->element_class)
11392                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11393
11394                 /*
11395                  * get the element_class from the current corlib.
11396                  */
11397                 ec = default_class_from_mono_type (enum_basetype);
11398                 klass->instance_size = ec->instance_size;
11399                 klass->size_inited = 1;
11400                 /* 
11401                  * this is almost safe to do with enums and it's needed to be able
11402                  * to create objects of the enum type (for use in SetConstant).
11403                  */
11404                 /* FIXME: Does this mean enums can't have method overrides ? */
11405                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11406         }
11407         mono_loader_unlock ();
11408 }
11409
11410 static MonoMarshalSpec*
11411 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11412                                                                 MonoReflectionMarshal *minfo)
11413 {
11414         MonoError error;
11415         MonoMarshalSpec *res;
11416
11417         res = image_g_new0 (image, MonoMarshalSpec, 1);
11418         res->native = (MonoMarshalNative)minfo->type;
11419
11420         switch (minfo->type) {
11421         case MONO_NATIVE_LPARRAY:
11422                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11423                 if (minfo->has_size) {
11424                         res->data.array_data.param_num = minfo->param_num;
11425                         res->data.array_data.num_elem = minfo->count;
11426                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11427                 }
11428                 else {
11429                         res->data.array_data.param_num = -1;
11430                         res->data.array_data.num_elem = -1;
11431                         res->data.array_data.elem_mult = -1;
11432                 }
11433                 break;
11434
11435         case MONO_NATIVE_BYVALTSTR:
11436         case MONO_NATIVE_BYVALARRAY:
11437                 res->data.array_data.num_elem = minfo->count;
11438                 break;
11439
11440         case MONO_NATIVE_CUSTOM:
11441                 if (minfo->marshaltyperef) {
11442                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11443                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11444                         res->data.custom_data.custom_name =
11445                                 type_get_fully_qualified_name (marshaltyperef);
11446                 }
11447                 if (minfo->mcookie)
11448                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11449                 break;
11450
11451         default:
11452                 break;
11453         }
11454
11455         return res;
11456 }
11457 #endif /* !DISABLE_REFLECTION_EMIT */
11458
11459 MonoReflectionMarshalAsAttribute*
11460 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11461                                                         MonoMarshalSpec *spec, MonoError *error)
11462 {
11463         MonoReflectionType *rt;
11464         MonoReflectionMarshalAsAttribute *minfo;
11465         MonoType *mtype;
11466
11467         mono_error_init (error);
11468         
11469         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11470         if (!minfo)
11471                 return NULL;
11472         minfo->utype = spec->native;
11473
11474         switch (minfo->utype) {
11475         case MONO_NATIVE_LPARRAY:
11476                 minfo->array_subtype = spec->data.array_data.elem_type;
11477                 minfo->size_const = spec->data.array_data.num_elem;
11478                 if (spec->data.array_data.param_num != -1)
11479                         minfo->size_param_index = spec->data.array_data.param_num;
11480                 break;
11481
11482         case MONO_NATIVE_BYVALTSTR:
11483         case MONO_NATIVE_BYVALARRAY:
11484                 minfo->size_const = spec->data.array_data.num_elem;
11485                 break;
11486
11487         case MONO_NATIVE_CUSTOM:
11488                 if (spec->data.custom_data.custom_name) {
11489                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11490                         if (mtype) {
11491                                 rt = mono_type_get_object_checked (domain, mtype, error);
11492                                 if (!rt)
11493                                         return NULL;
11494
11495                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11496                         }
11497
11498                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11499                 }
11500                 if (spec->data.custom_data.cookie)
11501                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11502                 break;
11503
11504         default:
11505                 break;
11506         }
11507
11508         return minfo;
11509 }
11510
11511 #ifndef DISABLE_REFLECTION_EMIT
11512 static MonoMethod*
11513 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11514                                          ReflectionMethodBuilder *rmb,
11515                                          MonoMethodSignature *sig)
11516 {
11517         MonoError error;
11518         MonoMethod *m;
11519         MonoMethodWrapper *wrapperm;
11520         MonoMarshalSpec **specs;
11521         MonoReflectionMethodAux *method_aux;
11522         MonoImage *image;
11523         gboolean dynamic;
11524         int i;
11525
11526         mono_error_init (&error);
11527         /*
11528          * Methods created using a MethodBuilder should have their memory allocated
11529          * inside the image mempool, while dynamic methods should have their memory
11530          * malloc'd.
11531          */
11532         dynamic = rmb->refs != NULL;
11533         image = dynamic ? NULL : klass->image;
11534
11535         if (!dynamic)
11536                 g_assert (!klass->generic_class);
11537
11538         mono_loader_lock ();
11539
11540         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11541                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11542                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11543         else
11544                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11545
11546         wrapperm = (MonoMethodWrapper*)m;
11547
11548         m->dynamic = dynamic;
11549         m->slot = -1;
11550         m->flags = rmb->attrs;
11551         m->iflags = rmb->iattrs;
11552         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11553         m->klass = klass;
11554         m->signature = sig;
11555         m->sre_method = TRUE;
11556         m->skip_visibility = rmb->skip_visibility;
11557         if (rmb->table_idx)
11558                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11559
11560         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11561                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11562                         m->string_ctor = 1;
11563
11564                 m->signature->pinvoke = 1;
11565         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11566                 m->signature->pinvoke = 1;
11567
11568                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11569
11570                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11571                 g_assert (mono_error_ok (&error));
11572                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11573                 g_assert (mono_error_ok (&error));
11574                 
11575                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11576
11577                 if (image_is_dynamic (klass->image))
11578                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11579
11580                 mono_loader_unlock ();
11581
11582                 return m;
11583         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11584                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11585                 MonoMethodHeader *header;
11586                 guint32 code_size;
11587                 gint32 max_stack, i;
11588                 gint32 num_locals = 0;
11589                 gint32 num_clauses = 0;
11590                 guint8 *code;
11591
11592                 if (rmb->ilgen) {
11593                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11594                         code_size = rmb->ilgen->code_len;
11595                         max_stack = rmb->ilgen->max_stack;
11596                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11597                         if (rmb->ilgen->ex_handlers)
11598                                 num_clauses = method_count_clauses (rmb->ilgen);
11599                 } else {
11600                         if (rmb->code) {
11601                                 code = mono_array_addr (rmb->code, guint8, 0);
11602                                 code_size = mono_array_length (rmb->code);
11603                                 /* we probably need to run a verifier on the code... */
11604                                 max_stack = 8; 
11605                         }
11606                         else {
11607                                 code = NULL;
11608                                 code_size = 0;
11609                                 max_stack = 8;
11610                         }
11611                 }
11612
11613                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11614                 header->code_size = code_size;
11615                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11616                 memcpy ((char*)header->code, code, code_size);
11617                 header->max_stack = max_stack;
11618                 header->init_locals = rmb->init_locals;
11619                 header->num_locals = num_locals;
11620
11621                 for (i = 0; i < num_locals; ++i) {
11622                         MonoReflectionLocalBuilder *lb = 
11623                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11624
11625                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11626                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11627                         mono_error_assert_ok (&error);
11628                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11629                 }
11630
11631                 header->num_clauses = num_clauses;
11632                 if (num_clauses) {
11633                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11634                                                                  rmb->ilgen, num_clauses, &error);
11635                         mono_error_assert_ok (&error);
11636                 }
11637
11638                 wrapperm->header = header;
11639         }
11640
11641         if (rmb->generic_params) {
11642                 int count = mono_array_length (rmb->generic_params);
11643                 MonoGenericContainer *container = rmb->generic_container;
11644
11645                 g_assert (container);
11646
11647                 container->type_argc = count;
11648                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11649                 container->owner.method = m;
11650                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11651
11652                 m->is_generic = TRUE;
11653                 mono_method_set_generic_container (m, container);
11654
11655                 for (i = 0; i < count; i++) {
11656                         MonoReflectionGenericParam *gp =
11657                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11658                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11659                         mono_error_assert_ok (&error);
11660                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11661                         container->type_params [i] = *param;
11662                 }
11663
11664                 /*
11665                  * The method signature might have pointers to generic parameters that belong to other methods.
11666                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11667                  * generic parameters.
11668                  */
11669                 for (i = 0; i < m->signature->param_count; ++i) {
11670                         MonoType *t = m->signature->params [i];
11671                         if (t->type == MONO_TYPE_MVAR) {
11672                                 MonoGenericParam *gparam =  t->data.generic_param;
11673                                 if (gparam->num < count) {
11674                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11675                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11676                                 }
11677
11678                         }
11679                 }
11680
11681                 if (klass->generic_container) {
11682                         container->parent = klass->generic_container;
11683                         container->context.class_inst = klass->generic_container->context.class_inst;
11684                 }
11685                 container->context.method_inst = mono_get_shared_generic_inst (container);
11686         }
11687
11688         if (rmb->refs) {
11689                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11690                 int i;
11691                 void **data;
11692
11693                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11694
11695                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11696                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11697                 for (i = 0; i < rmb->nrefs; ++i)
11698                         data [i + 1] = rmb->refs [i];
11699         }
11700
11701         method_aux = NULL;
11702
11703         /* Parameter info */
11704         if (rmb->pinfo) {
11705                 if (!method_aux)
11706                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11707                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11708                 for (i = 0; i <= m->signature->param_count; ++i) {
11709                         MonoReflectionParamBuilder *pb;
11710                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11711                                 if ((i > 0) && (pb->attrs)) {
11712                                         /* Make a copy since it might point to a shared type structure */
11713                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11714                                         m->signature->params [i - 1]->attrs = pb->attrs;
11715                                 }
11716
11717                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11718                                         MonoDynamicImage *assembly;
11719                                         guint32 idx, len;
11720                                         MonoTypeEnum def_type;
11721                                         char *p;
11722                                         const char *p2;
11723
11724                                         if (!method_aux->param_defaults) {
11725                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11726                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11727                                         }
11728                                         assembly = (MonoDynamicImage*)klass->image;
11729                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11730                                         /* Copy the data from the blob since it might get realloc-ed */
11731                                         p = assembly->blob.data + idx;
11732                                         len = mono_metadata_decode_blob_size (p, &p2);
11733                                         len += p2 - p;
11734                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11735                                         method_aux->param_default_types [i] = def_type;
11736                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11737                                 }
11738
11739                                 if (pb->name) {
11740                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11741                                         g_assert (mono_error_ok (&error));
11742                                 }
11743                                 if (pb->cattrs) {
11744                                         if (!method_aux->param_cattr)
11745                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11746                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11747                                 }
11748                         }
11749                 }
11750         }
11751
11752         /* Parameter marshalling */
11753         specs = NULL;
11754         if (rmb->pinfo)         
11755                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11756                         MonoReflectionParamBuilder *pb;
11757                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11758                                 if (pb->marshal_info) {
11759                                         if (specs == NULL)
11760                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11761                                         specs [pb->position] = 
11762                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11763                                 }
11764                         }
11765                 }
11766         if (specs != NULL) {
11767                 if (!method_aux)
11768                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11769                 method_aux->param_marshall = specs;
11770         }
11771
11772         if (image_is_dynamic (klass->image) && method_aux)
11773                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11774
11775         mono_loader_unlock ();
11776
11777         return m;
11778 }       
11779
11780 static MonoMethod*
11781 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11782 {
11783         ReflectionMethodBuilder rmb;
11784         MonoMethodSignature *sig;
11785
11786         mono_loader_lock ();
11787         sig = ctor_builder_to_signature (klass->image, mb);
11788         mono_loader_unlock ();
11789
11790         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11791                 return NULL;
11792
11793         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11794         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11795
11796         /* If we are in a generic class, we might be called multiple times from inflate_method */
11797         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11798                 /* ilgen is no longer needed */
11799                 mb->ilgen = NULL;
11800         }
11801
11802         return mb->mhandle;
11803 }
11804
11805 static MonoMethod*
11806 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11807 {
11808         ReflectionMethodBuilder rmb;
11809         MonoMethodSignature *sig;
11810
11811         mono_error_init (error);
11812
11813         mono_loader_lock ();
11814         sig = method_builder_to_signature (klass->image, mb);
11815         mono_loader_unlock ();
11816
11817         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11818                 return NULL;
11819
11820         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11821         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11822
11823         /* If we are in a generic class, we might be called multiple times from inflate_method */
11824         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11825                 /* ilgen is no longer needed */
11826                 mb->ilgen = NULL;
11827         }
11828         return mb->mhandle;
11829 }
11830
11831 static MonoClassField*
11832 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11833 {
11834         MonoClassField *field;
11835         MonoType *custom;
11836         MonoError error;
11837
11838         field = g_new0 (MonoClassField, 1);
11839
11840         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11841         g_assert (mono_error_ok (&error));
11842         if (fb->attrs || fb->modreq || fb->modopt) {
11843                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11844                 if (!is_ok (&error)) {
11845                         g_free (field);
11846                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11847                 }
11848                 field->type = mono_metadata_type_dup (NULL, type);
11849                 field->type->attrs = fb->attrs;
11850
11851                 g_assert (image_is_dynamic (klass->image));
11852                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11853                 g_free (field->type);
11854                 field->type = mono_metadata_type_dup (klass->image, custom);
11855                 g_free (custom);
11856         } else {
11857                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11858                 if (!is_ok (&error)) {
11859                         g_free (field);
11860                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11861                 }
11862         }
11863         if (fb->offset != -1)
11864                 field->offset = fb->offset;
11865         field->parent = klass;
11866         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11867
11868         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11869
11870         return field;
11871 }
11872 #endif
11873
11874 MonoType*
11875 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11876 {
11877         MonoError error;
11878         MonoClass *klass;
11879         MonoReflectionTypeBuilder *tb = NULL;
11880         gboolean is_dynamic = FALSE;
11881         MonoClass *geninst;
11882
11883         mono_loader_lock ();
11884
11885         if (is_sre_type_builder (mono_object_class (type))) {
11886                 tb = (MonoReflectionTypeBuilder *) type;
11887
11888                 is_dynamic = TRUE;
11889         } else if (is_sre_generic_instance (mono_object_class (type))) {
11890                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11891                 MonoReflectionType *gtd = rgi->generic_type;
11892
11893                 if (is_sre_type_builder (mono_object_class (gtd))) {
11894                         tb = (MonoReflectionTypeBuilder *)gtd;
11895                         is_dynamic = TRUE;
11896                 }
11897         }
11898
11899         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11900         if (tb && tb->generic_container)
11901                 mono_reflection_create_generic_class (tb);
11902
11903         MonoType *t = mono_reflection_type_get_handle (type, &error);
11904         mono_error_raise_exception (&error); /* FIXME don't raise here */
11905
11906         klass = mono_class_from_mono_type (t);
11907         if (!klass->generic_container) {
11908                 mono_loader_unlock ();
11909                 return NULL;
11910         }
11911
11912         if (klass->wastypebuilder) {
11913                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11914
11915                 is_dynamic = TRUE;
11916         }
11917
11918         mono_loader_unlock ();
11919
11920         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11921
11922         return &geninst->byval_arg;
11923 }
11924
11925 MonoClass*
11926 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11927 {
11928         MonoGenericClass *gclass;
11929         MonoGenericInst *inst;
11930
11931         g_assert (klass->generic_container);
11932
11933         inst = mono_metadata_get_generic_inst (type_argc, types);
11934         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11935
11936         return mono_generic_class_get_class (gclass);
11937 }
11938
11939 MonoReflectionMethod*
11940 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11941 {
11942         MonoError error;
11943         MonoClass *klass;
11944         MonoMethod *method, *inflated;
11945         MonoMethodInflated *imethod;
11946         MonoGenericContext tmp_context;
11947         MonoGenericInst *ginst;
11948         MonoType **type_argv;
11949         int count, i;
11950
11951         /*FIXME but this no longer should happen*/
11952         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11953 #ifndef DISABLE_REFLECTION_EMIT
11954                 MonoReflectionMethodBuilder *mb = NULL;
11955                 MonoType *tb;
11956                 MonoClass *klass;
11957
11958                 mb = (MonoReflectionMethodBuilder *) rmethod;
11959                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11960                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11961                 klass = mono_class_from_mono_type (tb);
11962
11963                 method = methodbuilder_to_mono_method (klass, mb, &error);
11964                 if (!method)
11965                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11966 #else
11967                 g_assert_not_reached ();
11968                 method = NULL;
11969 #endif
11970         } else {
11971                 method = rmethod->method;
11972         }
11973
11974         klass = method->klass;
11975
11976         if (method->is_inflated)
11977                 method = ((MonoMethodInflated *) method)->declaring;
11978
11979         count = mono_method_signature (method)->generic_param_count;
11980         if (count != mono_array_length (types))
11981                 return NULL;
11982
11983         type_argv = g_new0 (MonoType *, count);
11984         for (i = 0; i < count; i++) {
11985                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11986                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
11987                 if (!is_ok (&error)) {
11988                         g_free (type_argv);
11989                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11990                 }
11991         }
11992         ginst = mono_metadata_get_generic_inst (count, type_argv);
11993         g_free (type_argv);
11994
11995         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11996         tmp_context.method_inst = ginst;
11997
11998         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11999         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12000         imethod = (MonoMethodInflated *) inflated;
12001
12002         /*FIXME but I think this is no longer necessary*/
12003         if (image_is_dynamic (method->klass->image)) {
12004                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12005                 /*
12006                  * This table maps metadata structures representing inflated methods/fields
12007                  * to the reflection objects representing their generic definitions.
12008                  */
12009                 mono_image_lock ((MonoImage*)image);
12010                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12011                 mono_image_unlock ((MonoImage*)image);
12012         }
12013
12014         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12015                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12016         
12017         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12018         mono_error_raise_exception (&error); /* FIXME don't raise here */
12019         return ret;
12020 }
12021
12022 #ifndef DISABLE_REFLECTION_EMIT
12023
12024 static MonoMethod *
12025 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12026 {
12027         MonoMethodInflated *imethod;
12028         MonoGenericContext *context;
12029         int i;
12030
12031         /*
12032          * With generic code sharing the klass might not be inflated.
12033          * This can happen because classes inflated with their own
12034          * type arguments are "normalized" to the uninflated class.
12035          */
12036         if (!klass->generic_class)
12037                 return method;
12038
12039         context = mono_class_get_context (klass);
12040
12041         if (klass->method.count && klass->methods) {
12042                 /* Find the already created inflated method */
12043                 for (i = 0; i < klass->method.count; ++i) {
12044                         g_assert (klass->methods [i]->is_inflated);
12045                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12046                                 break;
12047                 }
12048                 g_assert (i < klass->method.count);
12049                 imethod = (MonoMethodInflated*)klass->methods [i];
12050         } else {
12051                 MonoError error;
12052                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12053                 mono_error_assert_ok (&error);
12054         }
12055
12056         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12057                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12058
12059                 mono_image_lock ((MonoImage*)image);
12060                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12061                 mono_image_unlock ((MonoImage*)image);
12062         }
12063         return (MonoMethod *) imethod;
12064 }
12065
12066 static MonoMethod *
12067 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12068 {
12069         MonoMethod *method;
12070         MonoClass *gklass;
12071
12072         mono_error_init (error);
12073
12074         MonoClass *type_class = mono_object_class (type);
12075
12076         if (is_sre_generic_instance (type_class)) {
12077                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12078                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12079                 return_val_if_nok (error, NULL);
12080                 gklass = mono_class_from_mono_type (generic_type);
12081         } else if (is_sre_type_builder (type_class)) {
12082                 MonoType *t = mono_reflection_type_get_handle (type, error);
12083                 return_val_if_nok (error, NULL);
12084                 gklass = mono_class_from_mono_type (t);
12085         } else if (type->type) {
12086                 gklass = mono_class_from_mono_type (type->type);
12087                 gklass = mono_class_get_generic_type_definition (gklass);
12088         } else {
12089                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12090         }
12091
12092         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12093                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12094                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12095                 else {
12096                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12097                         if (!method)
12098                                 return NULL;
12099                 }
12100         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12101                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12102                 if (!method)
12103                         return NULL;
12104         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12105                 method = ((MonoReflectionMethod *) obj)->method;
12106         else {
12107                 method = NULL; /* prevent compiler warning */
12108                 g_error ("can't handle type %s", obj->vtable->klass->name);
12109         }
12110
12111         MonoType *t = mono_reflection_type_get_handle (type, error);
12112         return_val_if_nok (error, NULL);
12113         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12114 }
12115
12116 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12117 void
12118 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12119 {
12120         MonoError error;
12121         MonoGenericClass *gclass;
12122         MonoDynamicGenericClass *dgclass;
12123         MonoClass *klass, *gklass;
12124         MonoType *gtype;
12125         int i;
12126
12127         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12128         mono_error_raise_exception (&error); /* FIXME don't raise here */
12129         klass = mono_class_from_mono_type (gtype);
12130         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12131         gclass = gtype->data.generic_class;
12132
12133         if (!gclass->is_dynamic)
12134                 return;
12135
12136         dgclass = (MonoDynamicGenericClass *) gclass;
12137
12138         if (dgclass->initialized)
12139                 return;
12140
12141         gklass = gclass->container_class;
12142         mono_class_init (gklass);
12143
12144         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12145
12146         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12147         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12148         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12149
12150         for (i = 0; i < dgclass->count_fields; i++) {
12151                 MonoError error;
12152                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12153                 MonoClassField *field, *inflated_field = NULL;
12154
12155                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12156                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12157                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12158                         field = ((MonoReflectionField *) obj)->field;
12159                 else {
12160                         field = NULL; /* prevent compiler warning */
12161                         g_assert_not_reached ();
12162                 }
12163
12164                 dgclass->fields [i] = *field;
12165                 dgclass->fields [i].parent = klass;
12166                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12167                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12168                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12169                 dgclass->field_generic_types [i] = field->type;
12170                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12171                 dgclass->field_objects [i] = obj;
12172
12173                 if (inflated_field) {
12174                         g_free (inflated_field);
12175                 } else {
12176                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12177                 }
12178         }
12179
12180         dgclass->initialized = TRUE;
12181 }
12182
12183 void
12184 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12185 {
12186         MonoDynamicGenericClass *dgclass;
12187         int i;
12188
12189         g_assert (gclass->is_dynamic);
12190
12191         dgclass = (MonoDynamicGenericClass *)gclass;
12192
12193         for (i = 0; i < dgclass->count_fields; ++i) {
12194                 MonoClassField *field = dgclass->fields + i;
12195                 mono_metadata_free_type (field->type);
12196                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12197         }
12198 }
12199
12200 static void
12201 fix_partial_generic_class (MonoClass *klass)
12202 {
12203         MonoClass *gklass = klass->generic_class->container_class;
12204         MonoDynamicGenericClass *dgclass;
12205         int i;
12206
12207         if (klass->wastypebuilder)
12208                 return;
12209
12210         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12211         if (klass->parent != gklass->parent) {
12212                 MonoError error;
12213                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12214                 if (mono_error_ok (&error)) {
12215                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12216                         mono_metadata_free_type (parent_type);
12217                         if (parent != klass->parent) {
12218                                 /*fool mono_class_setup_parent*/
12219                                 klass->supertypes = NULL;
12220                                 mono_class_setup_parent (klass, parent);
12221                         }
12222                 } else {
12223                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12224                         mono_error_cleanup (&error);
12225                         if (gklass->wastypebuilder)
12226                                 klass->wastypebuilder = TRUE;
12227                         return;
12228                 }
12229         }
12230
12231         if (!dgclass->initialized)
12232                 return;
12233
12234         if (klass->method.count != gklass->method.count) {
12235                 klass->method.count = gklass->method.count;
12236                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12237
12238                 for (i = 0; i < klass->method.count; i++) {
12239                         MonoError error;
12240                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12241                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12242                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12243                 }
12244         }
12245
12246         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12247                 klass->interface_count = gklass->interface_count;
12248                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12249                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12250
12251                 for (i = 0; i < gklass->interface_count; ++i) {
12252                         MonoError error;
12253                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12254                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12255
12256                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12257                         mono_metadata_free_type (iface_type);
12258
12259                         ensure_runtime_vtable (klass->interfaces [i], &error);
12260                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12261                 }
12262                 klass->interfaces_inited = 1;
12263         }
12264
12265         if (klass->field.count != gklass->field.count) {
12266                 klass->field.count = gklass->field.count;
12267                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12268
12269                 for (i = 0; i < klass->field.count; i++) {
12270                         MonoError error;
12271                         klass->fields [i] = gklass->fields [i];
12272                         klass->fields [i].parent = klass;
12273                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12274                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12275                 }
12276         }
12277
12278         /*We can only finish with this klass once it's parent has as well*/
12279         if (gklass->wastypebuilder)
12280                 klass->wastypebuilder = TRUE;
12281         return;
12282 }
12283
12284 /**
12285  * ensure_generic_class_runtime_vtable:
12286  * @klass a generic class
12287  * @error set on error
12288  *
12289  * Ensures that the generic container of @klass has a vtable and
12290  * returns TRUE on success.  On error returns FALSE and sets @error.
12291  */
12292 static gboolean
12293 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12294 {
12295         MonoClass *gklass = klass->generic_class->container_class;
12296
12297         mono_error_init (error);
12298
12299         if (!ensure_runtime_vtable (gklass, error))
12300                 return FALSE;
12301
12302         fix_partial_generic_class (klass);
12303
12304         return TRUE;
12305 }
12306
12307 /**
12308  * ensure_runtime_vtable:
12309  * @klass the class
12310  * @error set on error
12311  *
12312  * Ensures that @klass has a vtable and returns TRUE on success. On
12313  * error returns FALSE and sets @error.
12314  */
12315 static gboolean
12316 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12317 {
12318         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12319         int i, num, j;
12320
12321         mono_error_init (error);
12322
12323         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12324                 return TRUE;
12325         if (klass->parent)
12326                 if (!ensure_runtime_vtable (klass->parent, error))
12327                         return FALSE;
12328
12329         if (tb) {
12330                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12331                 num += tb->num_methods;
12332                 klass->method.count = num;
12333                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12334                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12335                 for (i = 0; i < num; ++i) {
12336                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12337                         if (!ctor)
12338                                 return FALSE;
12339                         klass->methods [i] = ctor;
12340                 }
12341                 num = tb->num_methods;
12342                 j = i;
12343                 for (i = 0; i < num; ++i) {
12344                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12345                         if (!meth)
12346                                 return FALSE;
12347                         klass->methods [j++] = meth;
12348                 }
12349         
12350                 if (tb->interfaces) {
12351                         klass->interface_count = mono_array_length (tb->interfaces);
12352                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12353                         for (i = 0; i < klass->interface_count; ++i) {
12354                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12355                                 return_val_if_nok (error, FALSE);
12356                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12357                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12358                                         return FALSE;
12359                         }
12360                         klass->interfaces_inited = 1;
12361                 }
12362         } else if (klass->generic_class){
12363                 if (!ensure_generic_class_runtime_vtable (klass, error))
12364                         return FALSE;
12365         }
12366
12367         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12368                 int slot_num = 0;
12369                 for (i = 0; i < klass->method.count; ++i) {
12370                         MonoMethod *im = klass->methods [i];
12371                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12372                                 im->slot = slot_num++;
12373                 }
12374                 
12375                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12376                 mono_class_setup_interface_offsets (klass);
12377                 mono_class_setup_interface_id (klass);
12378         }
12379
12380         /*
12381          * The generic vtable is needed even if image->run is not set since some
12382          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12383          * method->slot being defined.
12384          */
12385
12386         /* 
12387          * tb->methods could not be freed since it is used for determining 
12388          * overrides during dynamic vtable construction.
12389          */
12390
12391         return TRUE;
12392 }
12393
12394 static MonoMethod*
12395 mono_reflection_method_get_handle (MonoObject *method)
12396 {
12397         MonoError error;
12398         MonoClass *klass = mono_object_class (method);
12399         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12400                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12401                 return sr_method->method;
12402         }
12403         if (is_sre_method_builder (klass)) {
12404                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12405                 return mb->mhandle;
12406         }
12407         if (is_sre_method_on_tb_inst (klass)) {
12408                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12409                 MonoMethod *result;
12410                 /*FIXME move this to a proper method and unify with resolve_object*/
12411                 if (m->method_args) {
12412                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12413                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12414                 } else {
12415                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12416                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12417                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12418                         MonoMethod *mono_method;
12419
12420                         if (is_sre_method_builder (mono_object_class (m->mb)))
12421                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12422                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12423                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12424                         else
12425                                 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)));
12426
12427                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12428                 }
12429                 return result;
12430         }
12431
12432         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12433         return NULL;
12434 }
12435
12436 void
12437 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12438 {
12439         MonoReflectionTypeBuilder *tb;
12440         int i, j, onum;
12441         MonoReflectionMethod *m;
12442
12443         *overrides = NULL;
12444         *num_overrides = 0;
12445
12446         g_assert (image_is_dynamic (klass->image));
12447
12448         if (!mono_class_get_ref_info (klass))
12449                 return;
12450
12451         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12452
12453         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12454
12455         onum = 0;
12456         if (tb->methods) {
12457                 for (i = 0; i < tb->num_methods; ++i) {
12458                         MonoReflectionMethodBuilder *mb = 
12459                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12460                         if (mb->override_methods)
12461                                 onum += mono_array_length (mb->override_methods);
12462                 }
12463         }
12464
12465         if (onum) {
12466                 *overrides = g_new0 (MonoMethod*, onum * 2);
12467
12468                 onum = 0;
12469                 for (i = 0; i < tb->num_methods; ++i) {
12470                         MonoReflectionMethodBuilder *mb = 
12471                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12472                         if (mb->override_methods) {
12473                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12474                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12475
12476                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12477                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12478
12479                                         g_assert (mb->mhandle);
12480
12481                                         onum ++;
12482                                 }
12483                         }
12484                 }
12485         }
12486
12487         *num_overrides = onum;
12488 }
12489
12490 static void
12491 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12492 {
12493         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12494         MonoReflectionFieldBuilder *fb;
12495         MonoClassField *field;
12496         MonoImage *image = klass->image;
12497         const char *p, *p2;
12498         int i;
12499         guint32 len, idx, real_size = 0;
12500
12501         klass->field.count = tb->num_fields;
12502         klass->field.first = 0;
12503
12504         mono_error_init (error);
12505
12506         if (tb->class_size) {
12507                 if ((tb->packing_size & 0xffffff00) != 0) {
12508                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12509                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12510                         return;
12511                 }
12512                 klass->packing_size = tb->packing_size;
12513                 real_size = klass->instance_size + tb->class_size;
12514         }
12515
12516         if (!klass->field.count) {
12517                 klass->instance_size = MAX (klass->instance_size, real_size);
12518                 return;
12519         }
12520         
12521         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12522         mono_class_alloc_ext (klass);
12523         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12524         /*
12525         This is, guess what, a hack.
12526         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12527         On the static path no field class is resolved, only types are built. This is the right thing to do
12528         but we suck.
12529         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12530         */
12531         klass->size_inited = 1;
12532
12533         for (i = 0; i < klass->field.count; ++i) {
12534                 MonoArray *rva_data;
12535                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12536                 field = &klass->fields [i];
12537                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12538                 if (!mono_error_ok (error))
12539                         return;
12540                 if (fb->attrs) {
12541                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12542                         return_if_nok (error);
12543                         field->type = mono_metadata_type_dup (klass->image, type);
12544                         field->type->attrs = fb->attrs;
12545                 } else {
12546                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12547                         return_if_nok (error);
12548                 }
12549
12550                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12551                         char *base = mono_array_addr (rva_data, char, 0);
12552                         size_t size = mono_array_length (rva_data);
12553                         char *data = (char *)mono_image_alloc (klass->image, size);
12554                         memcpy (data, base, size);
12555                         klass->ext->field_def_values [i].data = data;
12556                 }
12557                 if (fb->offset != -1)
12558                         field->offset = fb->offset;
12559                 field->parent = klass;
12560                 fb->handle = field;
12561                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12562
12563                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12564                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12565                 }
12566                 if (fb->def_value) {
12567                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12568                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12569                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12570                         /* Copy the data from the blob since it might get realloc-ed */
12571                         p = assembly->blob.data + idx;
12572                         len = mono_metadata_decode_blob_size (p, &p2);
12573                         len += p2 - p;
12574                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12575                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12576                 }
12577         }
12578
12579         klass->instance_size = MAX (klass->instance_size, real_size);
12580         mono_class_layout_fields (klass);
12581 }
12582
12583 static void
12584 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12585 {
12586         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12587         MonoReflectionPropertyBuilder *pb;
12588         MonoImage *image = klass->image;
12589         MonoProperty *properties;
12590         int i;
12591
12592         mono_error_init (error);
12593
12594         if (!klass->ext)
12595                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12596
12597         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12598         klass->ext->property.first = 0;
12599
12600         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12601         klass->ext->properties = properties;
12602         for (i = 0; i < klass->ext->property.count; ++i) {
12603                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12604                 properties [i].parent = klass;
12605                 properties [i].attrs = pb->attrs;
12606                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12607                 if (!mono_error_ok (error))
12608                         return;
12609                 if (pb->get_method)
12610                         properties [i].get = pb->get_method->mhandle;
12611                 if (pb->set_method)
12612                         properties [i].set = pb->set_method->mhandle;
12613
12614                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12615                 if (pb->def_value) {
12616                         guint32 len, idx;
12617                         const char *p, *p2;
12618                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12619                         if (!klass->ext->prop_def_values)
12620                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12621                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12622                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12623                         /* Copy the data from the blob since it might get realloc-ed */
12624                         p = assembly->blob.data + idx;
12625                         len = mono_metadata_decode_blob_size (p, &p2);
12626                         len += p2 - p;
12627                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12628                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12629                 }
12630         }
12631 }
12632
12633 MonoReflectionEvent *
12634 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12635 {
12636         MonoError error;
12637         MonoEvent *event = g_new0 (MonoEvent, 1);
12638         MonoClass *klass;
12639
12640         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12641         mono_error_raise_exception (&error); /* FIXME don't raise here */
12642         klass = mono_class_from_mono_type (type);
12643
12644         event->parent = klass;
12645         event->attrs = eb->attrs;
12646         event->name = mono_string_to_utf8 (eb->name);
12647         if (eb->add_method)
12648                 event->add = eb->add_method->mhandle;
12649         if (eb->remove_method)
12650                 event->remove = eb->remove_method->mhandle;
12651         if (eb->raise_method)
12652                 event->raise = eb->raise_method->mhandle;
12653
12654 #ifndef MONO_SMALL_CONFIG
12655         if (eb->other_methods) {
12656                 int j;
12657                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12658                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12659                         MonoReflectionMethodBuilder *mb = 
12660                                 mono_array_get (eb->other_methods,
12661                                                 MonoReflectionMethodBuilder*, j);
12662                         event->other [j] = mb->mhandle;
12663                 }
12664         }
12665 #endif
12666
12667         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12668         mono_error_raise_exception (&error); /* FIXME don't raise here */
12669         return ev_obj;
12670 }
12671
12672 static void
12673 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12674 {
12675         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12676         MonoReflectionEventBuilder *eb;
12677         MonoImage *image = klass->image;
12678         MonoEvent *events;
12679         int i;
12680
12681         mono_error_init (error);
12682
12683         if (!klass->ext)
12684                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12685
12686         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12687         klass->ext->event.first = 0;
12688
12689         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12690         klass->ext->events = events;
12691         for (i = 0; i < klass->ext->event.count; ++i) {
12692                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12693                 events [i].parent = klass;
12694                 events [i].attrs = eb->attrs;
12695                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12696                 if (!mono_error_ok (error))
12697                         return;
12698                 if (eb->add_method)
12699                         events [i].add = eb->add_method->mhandle;
12700                 if (eb->remove_method)
12701                         events [i].remove = eb->remove_method->mhandle;
12702                 if (eb->raise_method)
12703                         events [i].raise = eb->raise_method->mhandle;
12704
12705 #ifndef MONO_SMALL_CONFIG
12706                 if (eb->other_methods) {
12707                         int j;
12708                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12709                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12710                                 MonoReflectionMethodBuilder *mb = 
12711                                         mono_array_get (eb->other_methods,
12712                                                                         MonoReflectionMethodBuilder*, j);
12713                                 events [i].other [j] = mb->mhandle;
12714                         }
12715                 }
12716 #endif
12717                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12718         }
12719 }
12720
12721 static gboolean
12722 remove_instantiations_of_and_ensure_contents (gpointer key,
12723                                                   gpointer value,
12724                                                   gpointer user_data)
12725 {
12726         MonoType *type = (MonoType*)key;
12727         MonoClass *klass = (MonoClass*)user_data;
12728
12729         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12730                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12731                 return TRUE;
12732         } else
12733                 return FALSE;
12734 }
12735
12736 static void
12737 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12738 {
12739         mono_error_init (error);
12740         int i;
12741
12742         if (!arr)
12743                 return;
12744
12745         for (i = 0; i < mono_array_length (arr); ++i) {
12746                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12747                 if (!mono_error_ok (error))
12748                         break;
12749         }
12750 }
12751
12752 MonoReflectionType*
12753 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12754 {
12755         MonoError error;
12756         MonoClass *klass;
12757         MonoDomain* domain;
12758         MonoReflectionType* res;
12759         int i, j;
12760
12761         domain = mono_object_domain (tb);
12762         klass = mono_class_from_mono_type (tb->type.type);
12763
12764         /*
12765          * Check for user defined Type subclasses.
12766          */
12767         RESOLVE_TYPE (tb->parent, &error);
12768         mono_error_raise_exception (&error); /* FIXME don't raise here */
12769         check_array_for_usertypes (tb->interfaces, &error);
12770         mono_error_raise_exception (&error); /*FIXME don't raise here */
12771         if (tb->fields) {
12772                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12773                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12774                         if (fb) {
12775                                 RESOLVE_TYPE (fb->type, &error);
12776                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12777                                 check_array_for_usertypes (fb->modreq, &error);
12778                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12779                                 check_array_for_usertypes (fb->modopt, &error);
12780                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12781                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12782                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12783                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12784                                 }
12785                         }
12786                 }
12787         }
12788         if (tb->methods) {
12789                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12790                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12791                         if (mb) {
12792                                 RESOLVE_TYPE (mb->rtype, &error);
12793                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12794                                 check_array_for_usertypes (mb->return_modreq, &error);
12795                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12796                                 check_array_for_usertypes (mb->return_modopt, &error);
12797                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12798                                 check_array_for_usertypes (mb->parameters, &error);
12799                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12800                                 if (mb->param_modreq)
12801                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12802                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12803                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12804                                         }
12805                                 if (mb->param_modopt)
12806                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12807                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12808                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12809                                         }
12810                         }
12811                 }
12812         }
12813         if (tb->ctors) {
12814                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12815                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12816                         if (mb) {
12817                                 check_array_for_usertypes (mb->parameters, &error);
12818                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12819                                 if (mb->param_modreq)
12820                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12821                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12822                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12823                                         }
12824                                 if (mb->param_modopt)
12825                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12826                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12827                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12828                                         }
12829                         }
12830                 }
12831         }
12832
12833         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12834
12835         /* 
12836          * we need to lock the domain because the lock will be taken inside
12837          * So, we need to keep the locking order correct.
12838          */
12839         mono_loader_lock ();
12840         mono_domain_lock (domain);
12841         if (klass->wastypebuilder) {
12842                 mono_domain_unlock (domain);
12843                 mono_loader_unlock ();
12844
12845                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12846                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12847
12848                 return res;
12849         }
12850         /*
12851          * Fields to set in klass:
12852          * the various flags: delegate/unicode/contextbound etc.
12853          */
12854         klass->flags = tb->attrs;
12855         klass->has_cctor = 1;
12856         klass->has_finalize = 1;
12857         klass->has_finalize_inited = 1;
12858
12859         mono_class_setup_parent (klass, klass->parent);
12860         /* fool mono_class_setup_supertypes */
12861         klass->supertypes = NULL;
12862         mono_class_setup_supertypes (klass);
12863         mono_class_setup_mono_type (klass);
12864
12865 #if 0
12866         if (!((MonoDynamicImage*)klass->image)->run) {
12867                 if (klass->generic_container) {
12868                         /* FIXME: The code below can't handle generic classes */
12869                         klass->wastypebuilder = TRUE;
12870                         mono_loader_unlock ();
12871                         mono_domain_unlock (domain);
12872
12873                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12874                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12875
12876                         return res;
12877                 }
12878         }
12879 #endif
12880
12881         /* enums are done right away */
12882         if (!klass->enumtype)
12883                 if (!ensure_runtime_vtable (klass, &error))
12884                         goto failure;
12885
12886         if (tb->subtypes) {
12887                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12888                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12889                         mono_class_alloc_ext (klass);
12890                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12891                         if (!is_ok (&error)) goto failure;
12892                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12893                 }
12894         }
12895
12896         klass->nested_classes_inited = TRUE;
12897
12898         /* fields and object layout */
12899         if (klass->parent) {
12900                 if (!klass->parent->size_inited)
12901                         mono_class_init (klass->parent);
12902                 klass->instance_size = klass->parent->instance_size;
12903                 klass->sizes.class_size = 0;
12904                 klass->min_align = klass->parent->min_align;
12905                 /* if the type has no fields we won't call the field_setup
12906                  * routine which sets up klass->has_references.
12907                  */
12908                 klass->has_references |= klass->parent->has_references;
12909         } else {
12910                 klass->instance_size = sizeof (MonoObject);
12911                 klass->min_align = 1;
12912         }
12913
12914         /* FIXME: handle packing_size and instance_size */
12915         typebuilder_setup_fields (klass, &error);
12916         if (!mono_error_ok (&error))
12917                 goto failure;
12918         typebuilder_setup_properties (klass, &error);
12919         if (!mono_error_ok (&error))
12920                 goto failure;
12921
12922         typebuilder_setup_events (klass, &error);
12923         if (!mono_error_ok (&error))
12924                 goto failure;
12925
12926         klass->wastypebuilder = TRUE;
12927
12928         /* 
12929          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12930          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12931          * we want to return normal System.MonoType objects, so clear these out from the cache.
12932          *
12933          * Together with this we must ensure the contents of all instances to match the created type.
12934          */
12935         if (domain->type_hash && klass->generic_container)
12936                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12937
12938         mono_domain_unlock (domain);
12939         mono_loader_unlock ();
12940
12941         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12942                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12943                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12944         }
12945
12946         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12947         mono_error_raise_exception (&error); /* FIXME don't raise here */
12948
12949         g_assert (res != (MonoReflectionType*)tb);
12950
12951         return res;
12952
12953 failure:
12954         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12955         klass->wastypebuilder = TRUE;
12956         mono_domain_unlock (domain);
12957         mono_loader_unlock ();
12958         mono_error_raise_exception (&error);
12959         return NULL;
12960 }
12961
12962 void
12963 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12964 {
12965         MonoGenericParamFull *param;
12966         MonoImage *image;
12967         MonoClass *pklass;
12968         MonoError error;
12969
12970         image = &gparam->tbuilder->module->dynamic_image->image;
12971
12972         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12973
12974         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12975         g_assert (mono_error_ok (&error));
12976         param->param.num = gparam->index;
12977
12978         if (gparam->mbuilder) {
12979                 if (!gparam->mbuilder->generic_container) {
12980                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
12981                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12982
12983                         MonoClass *klass = mono_class_from_mono_type (tb);
12984                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12985                         gparam->mbuilder->generic_container->is_method = TRUE;
12986                         /* 
12987                          * Cannot set owner.method, since the MonoMethod is not created yet.
12988                          * Set the image field instead, so type_in_image () works.
12989                          */
12990                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12991                         gparam->mbuilder->generic_container->owner.image = klass->image;
12992                 }
12993                 param->param.owner = gparam->mbuilder->generic_container;
12994         } else if (gparam->tbuilder) {
12995                 if (!gparam->tbuilder->generic_container) {
12996                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
12997                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12998                         MonoClass *klass = mono_class_from_mono_type (tb);
12999                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13000                         gparam->tbuilder->generic_container->owner.klass = klass;
13001                 }
13002                 param->param.owner = gparam->tbuilder->generic_container;
13003         }
13004
13005         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13006
13007         gparam->type.type = &pklass->byval_arg;
13008
13009         mono_class_set_ref_info (pklass, gparam);
13010         mono_image_append_class_to_reflection_info_set (pklass);
13011 }
13012
13013 MonoArray *
13014 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13015 {
13016         MonoError error;
13017         MonoReflectionModuleBuilder *module = sig->module;
13018         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13019         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13020         guint32 buflen, i;
13021         MonoArray *result;
13022         SigBuffer buf;
13023
13024         check_array_for_usertypes (sig->arguments, &error);
13025         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13026
13027         sigbuffer_init (&buf, 32);
13028
13029         sigbuffer_add_value (&buf, 0x07);
13030         sigbuffer_add_value (&buf, na);
13031         if (assembly != NULL){
13032                 for (i = 0; i < na; ++i) {
13033                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13034                         encode_reflection_type (assembly, type, &buf, &error);
13035                         if (!is_ok (&error)) goto fail;
13036                 }
13037         }
13038
13039         buflen = buf.p - buf.buf;
13040         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13041         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13042         sigbuffer_free (&buf);
13043         return result;
13044 fail:
13045         sigbuffer_free (&buf);
13046         mono_error_raise_exception (&error); /* FIXME don't raise here */
13047         return NULL;
13048 }
13049
13050 MonoArray *
13051 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13052 {
13053         MonoError error;
13054         MonoDynamicImage *assembly = sig->module->dynamic_image;
13055         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13056         guint32 buflen, i;
13057         MonoArray *result;
13058         SigBuffer buf;
13059
13060         check_array_for_usertypes (sig->arguments, &error);
13061         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13062
13063         sigbuffer_init (&buf, 32);
13064
13065         sigbuffer_add_value (&buf, 0x06);
13066         for (i = 0; i < na; ++i) {
13067                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13068                 encode_reflection_type (assembly, type, &buf, &error);
13069                 if (!is_ok (&error))
13070                         goto fail;
13071         }
13072
13073         buflen = buf.p - buf.buf;
13074         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13075         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13076         sigbuffer_free (&buf);
13077
13078         return result;
13079 fail:
13080         sigbuffer_free (&buf);
13081         mono_error_raise_exception (&error); /* FIXME don't raise here */
13082         return NULL;
13083 }
13084
13085 typedef struct {
13086         MonoMethod *handle;
13087         MonoDomain *domain;
13088 } DynamicMethodReleaseData;
13089
13090 /*
13091  * The runtime automatically clean up those after finalization.
13092 */      
13093 static MonoReferenceQueue *dynamic_method_queue;
13094
13095 static void
13096 free_dynamic_method (void *dynamic_method)
13097 {
13098         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13099         MonoDomain *domain = data->domain;
13100         MonoMethod *method = data->handle;
13101         guint32 dis_link;
13102
13103         mono_domain_lock (domain);
13104         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13105         g_hash_table_remove (domain->method_to_dyn_method, method);
13106         mono_domain_unlock (domain);
13107         g_assert (dis_link);
13108         mono_gchandle_free (dis_link);
13109
13110         mono_runtime_free_method (domain, method);
13111         g_free (data);
13112 }
13113
13114 void 
13115 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13116 {
13117         MonoError error;
13118         MonoReferenceQueue *queue;
13119         MonoMethod *handle;
13120         DynamicMethodReleaseData *release_data;
13121         ReflectionMethodBuilder rmb;
13122         MonoMethodSignature *sig;
13123         MonoClass *klass;
13124         MonoDomain *domain;
13125         GSList *l;
13126         int i;
13127
13128         if (mono_runtime_is_shutting_down ())
13129                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13130
13131         if (!(queue = dynamic_method_queue)) {
13132                 mono_loader_lock ();
13133                 if (!(queue = dynamic_method_queue))
13134                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13135                 mono_loader_unlock ();
13136         }
13137
13138         sig = dynamic_method_to_signature (mb);
13139
13140         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13141
13142         /*
13143          * Resolve references.
13144          */
13145         /* 
13146          * Every second entry in the refs array is reserved for storing handle_class,
13147          * which is needed by the ldtoken implementation in the JIT.
13148          */
13149         rmb.nrefs = mb->nrefs;
13150         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13151         for (i = 0; i < mb->nrefs; i += 2) {
13152                 MonoClass *handle_class;
13153                 gpointer ref;
13154                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13155
13156                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13157                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13158                         /*
13159                          * The referenced DynamicMethod should already be created by the managed
13160                          * code, except in the case of circular references. In that case, we store
13161                          * method in the refs array, and fix it up later when the referenced 
13162                          * DynamicMethod is created.
13163                          */
13164                         if (method->mhandle) {
13165                                 ref = method->mhandle;
13166                         } else {
13167                                 /* FIXME: GC object stored in unmanaged memory */
13168                                 ref = method;
13169
13170                                 /* FIXME: GC object stored in unmanaged memory */
13171                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13172                         }
13173                         handle_class = mono_defaults.methodhandle_class;
13174                 } else {
13175                         MonoException *ex = NULL;
13176                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13177                         if (!ref)
13178                                 ex = mono_get_exception_type_load (NULL, NULL);
13179                         else if (mono_security_core_clr_enabled ())
13180                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13181
13182                         if (ex) {
13183                                 g_free (rmb.refs);
13184                                 mono_raise_exception (ex);
13185                                 return;
13186                         }
13187                 }
13188
13189                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13190                 rmb.refs [i + 1] = handle_class;
13191         }               
13192
13193         if (mb->owner) {
13194                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13195                 if (!is_ok (&error)) {
13196                         g_free (rmb.refs);
13197                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13198                 }
13199                 klass = mono_class_from_mono_type (owner_type);
13200         } else {
13201                 klass = mono_defaults.object_class;
13202         }
13203
13204         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13205         release_data = g_new (DynamicMethodReleaseData, 1);
13206         release_data->handle = handle;
13207         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13208         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13209                 g_free (release_data);
13210
13211         /* Fix up refs entries pointing at us */
13212         for (l = mb->referenced_by; l; l = l->next) {
13213                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13214                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13215                 gpointer *data;
13216                 
13217                 g_assert (method->mhandle);
13218
13219                 data = (gpointer*)wrapper->method_data;
13220                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13221                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13222                                 data [i + 1] = mb->mhandle;
13223                 }
13224         }
13225         g_slist_free (mb->referenced_by);
13226
13227         g_free (rmb.refs);
13228
13229         /* ilgen is no longer needed */
13230         mb->ilgen = NULL;
13231
13232         domain = mono_domain_get ();
13233         mono_domain_lock (domain);
13234         if (!domain->method_to_dyn_method)
13235                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13236         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13237         mono_domain_unlock (domain);
13238 }
13239
13240 #endif /* DISABLE_REFLECTION_EMIT */
13241
13242 /**
13243  * 
13244  * mono_reflection_is_valid_dynamic_token:
13245  * 
13246  * Returns TRUE if token is valid.
13247  * 
13248  */
13249 gboolean
13250 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13251 {
13252         return lookup_dyn_token (image, token) != NULL;
13253 }
13254
13255 MonoMethodSignature *
13256 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13257 {
13258         MonoMethodSignature *sig;
13259         g_assert (image_is_dynamic (image));
13260
13261         mono_error_init (error);
13262
13263         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13264         if (sig)
13265                 return sig;
13266
13267         return mono_method_signature_checked (method, error);
13268 }
13269
13270 #ifndef DISABLE_REFLECTION_EMIT
13271
13272 /**
13273  * mono_reflection_lookup_dynamic_token:
13274  *
13275  * Finish the Builder object pointed to by TOKEN and return the corresponding
13276  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13277  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13278  * mapping table.
13279  *
13280  * LOCKING: Take the loader lock
13281  */
13282 gpointer
13283 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13284 {
13285         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13286         MonoObject *obj;
13287         MonoClass *klass;
13288
13289         obj = lookup_dyn_token (assembly, token);
13290         if (!obj) {
13291                 if (valid_token)
13292                         g_error ("Could not find required dynamic token 0x%08x", token);
13293                 else
13294                         return NULL;
13295         }
13296
13297         if (!handle_class)
13298                 handle_class = &klass;
13299         return resolve_object (image, obj, handle_class, context);
13300 }
13301
13302 /*
13303  * ensure_complete_type:
13304  *
13305  *   Ensure that KLASS is completed if it is a dynamic type, or references
13306  * dynamic types.
13307  */
13308 static void
13309 ensure_complete_type (MonoClass *klass)
13310 {
13311         MonoError error;
13312
13313         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13314                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13315
13316                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13317                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13318
13319                 // Asserting here could break a lot of code
13320                 //g_assert (klass->wastypebuilder);
13321         }
13322
13323         if (klass->generic_class) {
13324                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13325                 int i;
13326
13327                 for (i = 0; i < inst->type_argc; ++i) {
13328                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13329                 }
13330         }
13331 }
13332
13333 static gpointer
13334 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13335 {
13336         MonoError error;
13337         gpointer result = NULL;
13338
13339         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13340                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13341                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13342                 *handle_class = mono_defaults.string_class;
13343                 g_assert (result);
13344         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13345                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13346                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13347                 MonoClass *mc = mono_class_from_mono_type (type);
13348                 if (!mono_class_init (mc))
13349                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13350
13351                 if (context) {
13352                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13353                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13354
13355                         result = mono_class_from_mono_type (inflated);
13356                         mono_metadata_free_type (inflated);
13357                 } else {
13358                         result = mono_class_from_mono_type (type);
13359                 }
13360                 *handle_class = mono_defaults.typehandle_class;
13361                 g_assert (result);
13362         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13363                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13364                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13365                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13366                 result = ((MonoReflectionMethod*)obj)->method;
13367                 if (context) {
13368                         MonoError error;
13369                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13370                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13371                 }
13372                 *handle_class = mono_defaults.methodhandle_class;
13373                 g_assert (result);
13374         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13375                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13376                 result = mb->mhandle;
13377                 if (!result) {
13378                         /* Type is not yet created */
13379                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13380
13381                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13382                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13383
13384                         /*
13385                          * Hopefully this has been filled in by calling CreateType() on the
13386                          * TypeBuilder.
13387                          */
13388                         /*
13389                          * TODO: This won't work if the application finishes another 
13390                          * TypeBuilder instance instead of this one.
13391                          */
13392                         result = mb->mhandle;
13393                 }
13394                 if (context) {
13395                         MonoError error;
13396                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13397                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13398                 }
13399                 *handle_class = mono_defaults.methodhandle_class;
13400         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13401                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13402
13403                 result = cb->mhandle;
13404                 if (!result) {
13405                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13406
13407                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13408                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13409                         result = cb->mhandle;
13410                 }
13411                 if (context) {
13412                         MonoError error;
13413                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13414                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13415                 }
13416                 *handle_class = mono_defaults.methodhandle_class;
13417         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13418                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13419
13420                 ensure_complete_type (field->parent);
13421                 if (context) {
13422                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13423                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13424
13425                         MonoClass *klass = mono_class_from_mono_type (inflated);
13426                         MonoClassField *inflated_field;
13427                         gpointer iter = NULL;
13428                         mono_metadata_free_type (inflated);
13429                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13430                                 if (!strcmp (field->name, inflated_field->name))
13431                                         break;
13432                         }
13433                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13434                         result = inflated_field;
13435                 } else {
13436                         result = field;
13437                 }
13438                 *handle_class = mono_defaults.fieldhandle_class;
13439                 g_assert (result);
13440         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13441                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13442                 result = fb->handle;
13443
13444                 if (!result) {
13445                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13446
13447                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13448                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13449                         result = fb->handle;
13450                 }
13451
13452                 if (fb->handle && fb->handle->parent->generic_container) {
13453                         MonoClass *klass = fb->handle->parent;
13454                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13455                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13456
13457                         MonoClass *inflated = mono_class_from_mono_type (type);
13458
13459                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13460                         g_assert (result);
13461                         mono_metadata_free_type (type);
13462                 }
13463                 *handle_class = mono_defaults.fieldhandle_class;
13464         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13465                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13466                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13467                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13468                 MonoClass *klass;
13469
13470                 klass = type->data.klass;
13471                 if (klass->wastypebuilder) {
13472                         /* Already created */
13473                         result = klass;
13474                 }
13475                 else {
13476                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13477                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13478                         result = type->data.klass;
13479                         g_assert (result);
13480                 }
13481                 *handle_class = mono_defaults.typehandle_class;
13482         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13483                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13484                 MonoMethodSignature *sig;
13485                 int nargs, i;
13486
13487                 if (helper->arguments)
13488                         nargs = mono_array_length (helper->arguments);
13489                 else
13490                         nargs = 0;
13491
13492                 sig = mono_metadata_signature_alloc (image, nargs);
13493                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13494                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13495
13496                 if (helper->unmanaged_call_conv) { /* unmanaged */
13497                         sig->call_convention = helper->unmanaged_call_conv - 1;
13498                         sig->pinvoke = TRUE;
13499                 } else if (helper->call_conv & 0x02) {
13500                         sig->call_convention = MONO_CALL_VARARG;
13501                 } else {
13502                         sig->call_convention = MONO_CALL_DEFAULT;
13503                 }
13504
13505                 sig->param_count = nargs;
13506                 /* TODO: Copy type ? */
13507                 sig->ret = helper->return_type->type;
13508                 for (i = 0; i < nargs; ++i) {
13509                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13510                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13511                 }
13512
13513                 result = sig;
13514                 *handle_class = NULL;
13515         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13516                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13517                 /* Already created by the managed code */
13518                 g_assert (method->mhandle);
13519                 result = method->mhandle;
13520                 *handle_class = mono_defaults.methodhandle_class;
13521         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13522                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13523                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13524                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13525                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13526
13527                 result = mono_class_from_mono_type (type);
13528                 *handle_class = mono_defaults.typehandle_class;
13529                 g_assert (result);
13530                 mono_metadata_free_type (type);
13531         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13532                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13533                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13534                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13535                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13536
13537                 result = mono_class_from_mono_type (type);
13538                 *handle_class = mono_defaults.typehandle_class;
13539                 g_assert (result);
13540                 mono_metadata_free_type (type);
13541         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13542                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13543                 MonoClass *inflated;
13544                 MonoType *type;
13545                 MonoClassField *field;
13546
13547                 if (is_sre_field_builder (mono_object_class (f->fb)))
13548                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13549                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13550                         field = ((MonoReflectionField*)f->fb)->field;
13551                 else
13552                         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)));
13553
13554                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13555                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13556                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13557                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13558
13559                 inflated = mono_class_from_mono_type (type);
13560
13561                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13562                 ensure_complete_type (field->parent);
13563                 g_assert (result);
13564                 mono_metadata_free_type (type);
13565                 *handle_class = mono_defaults.fieldhandle_class;
13566         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13567                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13568                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13569                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13570                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13571                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13572
13573                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13574                 MonoMethod *method;
13575
13576                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13577                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13578                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13579                         method = ((MonoReflectionMethod *)c->cb)->method;
13580                 else
13581                         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)));
13582
13583                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13584                 *handle_class = mono_defaults.methodhandle_class;
13585                 mono_metadata_free_type (type);
13586         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13587                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13588                 if (m->method_args) {
13589                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13590                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13591                         if (context) {
13592                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13593                                 mono_error_assert_ok (&error);
13594                         }
13595                 } else {
13596                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13597                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13598                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13599                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13600
13601                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13602                         MonoMethod *method;
13603
13604                         if (is_sre_method_builder (mono_object_class (m->mb)))
13605                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13606                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13607                                 method = ((MonoReflectionMethod *)m->mb)->method;
13608                         else
13609                                 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)));
13610
13611                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13612                         mono_metadata_free_type (type);
13613                 }
13614                 *handle_class = mono_defaults.methodhandle_class;
13615         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13616                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13617                 MonoType *mtype;
13618                 MonoClass *klass;
13619                 MonoMethod *method;
13620                 gpointer iter;
13621                 char *name;
13622
13623                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13624                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13625                 klass = mono_class_from_mono_type (mtype);
13626
13627                 /* Find the method */
13628
13629                 name = mono_string_to_utf8 (m->name);
13630                 iter = NULL;
13631                 while ((method = mono_class_get_methods (klass, &iter))) {
13632                         if (!strcmp (method->name, name))
13633                                 break;
13634                 }
13635                 g_free (name);
13636
13637                 // FIXME:
13638                 g_assert (method);
13639                 // FIXME: Check parameters/return value etc. match
13640
13641                 result = method;
13642                 *handle_class = mono_defaults.methodhandle_class;
13643         } else if (is_sre_array (mono_object_get_class(obj)) ||
13644                                 is_sre_byref (mono_object_get_class(obj)) ||
13645                                 is_sre_pointer (mono_object_get_class(obj))) {
13646                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13647                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13648                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13649
13650                 if (context) {
13651                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13652                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13653
13654                         result = mono_class_from_mono_type (inflated);
13655                         mono_metadata_free_type (inflated);
13656                 } else {
13657                         result = mono_class_from_mono_type (type);
13658                 }
13659                 *handle_class = mono_defaults.typehandle_class;
13660         } else {
13661                 g_print ("%s\n", obj->vtable->klass->name);
13662                 g_assert_not_reached ();
13663         }
13664         return result;
13665 }
13666
13667 #else /* DISABLE_REFLECTION_EMIT */
13668
13669 MonoArray*
13670 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13671 {
13672         g_assert_not_reached ();
13673         return NULL;
13674 }
13675
13676 void
13677 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13678 {
13679         g_assert_not_reached ();
13680 }
13681
13682 void
13683 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13684 {
13685         g_assert_not_reached ();
13686 }
13687
13688 void
13689 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13690 {
13691         g_assert_not_reached ();
13692 }
13693
13694 void
13695 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13696 {
13697         g_assert_not_reached ();
13698 }
13699
13700 void
13701 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13702 {
13703         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13704 }
13705
13706 void
13707 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13708 {
13709         g_assert_not_reached ();
13710 }
13711
13712 void
13713 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13714 {
13715         g_assert_not_reached ();
13716 }
13717
13718 MonoReflectionModule *
13719 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13720 {
13721         g_assert_not_reached ();
13722         return NULL;
13723 }
13724
13725 guint32
13726 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13727 {
13728         g_assert_not_reached ();
13729         return 0;
13730 }
13731
13732 guint32
13733 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13734 {
13735         g_assert_not_reached ();
13736         return 0;
13737 }
13738
13739 guint32
13740 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13741                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13742 {
13743         g_assert_not_reached ();
13744         return 0;
13745 }
13746
13747 void
13748 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13749 {
13750 }
13751
13752 void
13753 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13754 {
13755         g_assert_not_reached ();
13756 }
13757
13758 void
13759 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13760 {
13761         *overrides = NULL;
13762         *num_overrides = 0;
13763 }
13764
13765 MonoReflectionEvent *
13766 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13767 {
13768         g_assert_not_reached ();
13769         return NULL;
13770 }
13771
13772 MonoReflectionType*
13773 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13774 {
13775         g_assert_not_reached ();
13776         return NULL;
13777 }
13778
13779 void
13780 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13781 {
13782         g_assert_not_reached ();
13783 }
13784
13785 MonoArray *
13786 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13787 {
13788         g_assert_not_reached ();
13789         return NULL;
13790 }
13791
13792 MonoArray *
13793 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13794 {
13795         g_assert_not_reached ();
13796         return NULL;
13797 }
13798
13799 void 
13800 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13801 {
13802 }
13803
13804 gpointer
13805 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13806 {
13807         return NULL;
13808 }
13809
13810 MonoType*
13811 mono_reflection_type_get_handle (MonoReflectionType* ref)
13812 {
13813         if (!ref)
13814                 return NULL;
13815         return ref->type;
13816 }
13817
13818 void
13819 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13820 {
13821         g_assert_not_reached ();
13822 }
13823
13824 #endif /* DISABLE_REFLECTION_EMIT */
13825
13826 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13827 const static guint32 declsec_flags_map[] = {
13828         0x00000000,                                     /* empty */
13829         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13830         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13831         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13832         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13833         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13834         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13835         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13836         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13837         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13838         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13839         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13840         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13841         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13842         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13843         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13844         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13845         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13846         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13847 };
13848
13849 /*
13850  * Returns flags that includes all available security action associated to the handle.
13851  * @token: metadata token (either for a class or a method)
13852  * @image: image where resides the metadata.
13853  */
13854 static guint32
13855 mono_declsec_get_flags (MonoImage *image, guint32 token)
13856 {
13857         int index = mono_metadata_declsec_from_index (image, token);
13858         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13859         guint32 result = 0;
13860         guint32 action;
13861         int i;
13862
13863         /* HasSecurity can be present for other, not specially encoded, attributes,
13864            e.g. SuppressUnmanagedCodeSecurityAttribute */
13865         if (index < 0)
13866                 return 0;
13867
13868         for (i = index; i < t->rows; i++) {
13869                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13870
13871                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13872                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13873                         break;
13874
13875                 action = cols [MONO_DECL_SECURITY_ACTION];
13876                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13877                         result |= declsec_flags_map [action];
13878                 } else {
13879                         g_assert_not_reached ();
13880                 }
13881         }
13882         return result;
13883 }
13884
13885 /*
13886  * Get the security actions (in the form of flags) associated with the specified method.
13887  *
13888  * @method: The method for which we want the declarative security flags.
13889  * Return the declarative security flags for the method (only).
13890  *
13891  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13892  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13893  */
13894 guint32
13895 mono_declsec_flags_from_method (MonoMethod *method)
13896 {
13897         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13898                 /* FIXME: No cache (for the moment) */
13899                 guint32 idx = mono_method_get_index (method);
13900                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13901                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13902                 return mono_declsec_get_flags (method->klass->image, idx);
13903         }
13904         return 0;
13905 }
13906
13907 /*
13908  * Get the security actions (in the form of flags) associated with the specified class.
13909  *
13910  * @klass: The class for which we want the declarative security flags.
13911  * Return the declarative security flags for the class.
13912  *
13913  * Note: We cache the flags inside the MonoClass structure as this will get 
13914  *       called very often (at least for each method).
13915  */
13916 guint32
13917 mono_declsec_flags_from_class (MonoClass *klass)
13918 {
13919         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13920                 if (!klass->ext || !klass->ext->declsec_flags) {
13921                         guint32 idx;
13922
13923                         idx = mono_metadata_token_index (klass->type_token);
13924                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13925                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13926                         mono_loader_lock ();
13927                         mono_class_alloc_ext (klass);
13928                         mono_loader_unlock ();
13929                         /* we cache the flags on classes */
13930                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13931                 }
13932                 return klass->ext->declsec_flags;
13933         }
13934         return 0;
13935 }
13936
13937 /*
13938  * Get the security actions (in the form of flags) associated with the specified assembly.
13939  *
13940  * @assembly: The assembly for which we want the declarative security flags.
13941  * Return the declarative security flags for the assembly.
13942  */
13943 guint32
13944 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13945 {
13946         guint32 idx = 1; /* there is only one assembly */
13947         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13948         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13949         return mono_declsec_get_flags (assembly->image, idx);
13950 }
13951
13952
13953 /*
13954  * Fill actions for the specific index (which may either be an encoded class token or
13955  * an encoded method token) from the metadata image.
13956  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13957  */
13958 static MonoBoolean
13959 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13960         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13961 {
13962         MonoBoolean result = FALSE;
13963         MonoTableInfo *t;
13964         guint32 cols [MONO_DECL_SECURITY_SIZE];
13965         int index = mono_metadata_declsec_from_index (image, token);
13966         int i;
13967
13968         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13969         for (i = index; i < t->rows; i++) {
13970                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13971
13972                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13973                         return result;
13974
13975                 /* if present only replace (class) permissions with method permissions */
13976                 /* if empty accept either class or method permissions */
13977                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13978                         if (!actions->demand.blob) {
13979                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13980                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13981                                 actions->demand.blob = (char*) (blob + 2);
13982                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13983                                 result = TRUE;
13984                         }
13985                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13986                         if (!actions->noncasdemand.blob) {
13987                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13988                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13989                                 actions->noncasdemand.blob = (char*) (blob + 2);
13990                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13991                                 result = TRUE;
13992                         }
13993                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13994                         if (!actions->demandchoice.blob) {
13995                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13996                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13997                                 actions->demandchoice.blob = (char*) (blob + 2);
13998                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13999                                 result = TRUE;
14000                         }
14001                 }
14002         }
14003
14004         return result;
14005 }
14006
14007 static MonoBoolean
14008 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14009         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14010 {
14011         guint32 idx = mono_metadata_token_index (klass->type_token);
14012         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14013         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14014         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14015 }
14016
14017 static MonoBoolean
14018 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14019         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14020 {
14021         guint32 idx = mono_method_get_index (method);
14022         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14023         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14024         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14025 }
14026
14027 /*
14028  * Collect all actions (that requires to generate code in mini) assigned for
14029  * the specified method.
14030  * Note: Don't use the content of actions if the function return FALSE.
14031  */
14032 MonoBoolean
14033 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14034 {
14035         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14036                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14037         MonoBoolean result = FALSE;
14038         guint32 flags;
14039
14040         /* quick exit if no declarative security is present in the metadata */
14041         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14042                 return FALSE;
14043
14044         /* we want the original as the wrapper is "free" of the security informations */
14045         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14046                 method = mono_marshal_method_from_wrapper (method);
14047                 if (!method)
14048                         return FALSE;
14049         }
14050
14051         /* First we look for method-level attributes */
14052         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14053                 mono_class_init (method->klass);
14054                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14055
14056                 result = mono_declsec_get_method_demands_params (method, demands, 
14057                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14058         }
14059
14060         /* Here we use (or create) the class declarative cache to look for demands */
14061         flags = mono_declsec_flags_from_class (method->klass);
14062         if (flags & mask) {
14063                 if (!result) {
14064                         mono_class_init (method->klass);
14065                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14066                 }
14067                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14068                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14069         }
14070
14071         /* The boolean return value is used as a shortcut in case nothing needs to
14072            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14073         return result;
14074 }
14075
14076
14077 /*
14078  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14079  *
14080  * Note: Don't use the content of actions if the function return FALSE.
14081  */
14082 MonoBoolean
14083 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14084 {
14085         MonoBoolean result = FALSE;
14086         guint32 flags;
14087
14088         /* quick exit if no declarative security is present in the metadata */
14089         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14090                 return FALSE;
14091
14092         /* we want the original as the wrapper is "free" of the security informations */
14093         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14094                 method = mono_marshal_method_from_wrapper (method);
14095                 if (!method)
14096                         return FALSE;
14097         }
14098
14099         /* results are independant - zeroize both */
14100         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14101         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14102
14103         /* First we look for method-level attributes */
14104         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14105                 mono_class_init (method->klass);
14106
14107                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14108                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14109         }
14110
14111         /* Here we use (or create) the class declarative cache to look for demands */
14112         flags = mono_declsec_flags_from_class (method->klass);
14113         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14114                 mono_class_init (method->klass);
14115
14116                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14117                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14118         }
14119
14120         return result;
14121 }
14122
14123 /*
14124  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14125  *
14126  * @klass       The inherited class - this is the class that provides the security check (attributes)
14127  * @demans      
14128  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14129  * 
14130  * Note: Don't use the content of actions if the function return FALSE.
14131  */
14132 MonoBoolean
14133 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14134 {
14135         MonoBoolean result = FALSE;
14136         guint32 flags;
14137
14138         /* quick exit if no declarative security is present in the metadata */
14139         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14140                 return FALSE;
14141
14142         /* Here we use (or create) the class declarative cache to look for demands */
14143         flags = mono_declsec_flags_from_class (klass);
14144         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14145                 mono_class_init (klass);
14146                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14147
14148                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14149                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14150         }
14151
14152         return result;
14153 }
14154
14155 /*
14156  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14157  *
14158  * Note: Don't use the content of actions if the function return FALSE.
14159  */
14160 MonoBoolean
14161 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14162 {
14163         /* quick exit if no declarative security is present in the metadata */
14164         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14165                 return FALSE;
14166
14167         /* we want the original as the wrapper is "free" of the security informations */
14168         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14169                 method = mono_marshal_method_from_wrapper (method);
14170                 if (!method)
14171                         return FALSE;
14172         }
14173
14174         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14175                 mono_class_init (method->klass);
14176                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14177
14178                 return mono_declsec_get_method_demands_params (method, demands, 
14179                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14180         }
14181         return FALSE;
14182 }
14183
14184
14185 static MonoBoolean
14186 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14187 {
14188         guint32 cols [MONO_DECL_SECURITY_SIZE];
14189         MonoTableInfo *t;
14190         int i;
14191
14192         int index = mono_metadata_declsec_from_index (image, token);
14193         if (index == -1)
14194                 return FALSE;
14195
14196         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14197         for (i = index; i < t->rows; i++) {
14198                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14199
14200                 /* shortcut - index are ordered */
14201                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14202                         return FALSE;
14203
14204                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14205                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14206                         entry->blob = (char*) (metadata + 2);
14207                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14208                         return TRUE;
14209                 }
14210         }
14211
14212         return FALSE;
14213 }
14214
14215 MonoBoolean
14216 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14217 {
14218         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14219                 guint32 idx = mono_method_get_index (method);
14220                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14221                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14222                 return get_declsec_action (method->klass->image, idx, action, entry);
14223         }
14224         return FALSE;
14225 }
14226
14227 MonoBoolean
14228 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14229 {
14230         /* use cache */
14231         guint32 flags = mono_declsec_flags_from_class (klass);
14232         if (declsec_flags_map [action] & flags) {
14233                 guint32 idx = mono_metadata_token_index (klass->type_token);
14234                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14235                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14236                 return get_declsec_action (klass->image, idx, action, entry);
14237         }
14238         return FALSE;
14239 }
14240
14241 MonoBoolean
14242 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14243 {
14244         guint32 idx = 1; /* there is only one assembly */
14245         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14246         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14247
14248         return get_declsec_action (assembly->image, idx, action, entry);
14249 }
14250
14251 gboolean
14252 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14253 {
14254         MonoError error;
14255         MonoObject *res, *exc;
14256         void *params [1];
14257         static MonoMethod *method = NULL;
14258
14259         if (method == NULL) {
14260                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14261                 g_assert (method);
14262         }
14263
14264         /* 
14265          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14266          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14267          */
14268         g_assert (mono_class_get_ref_info (klass));
14269         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14270
14271         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14272         mono_error_raise_exception (&error); /* FIXME don't raise here */
14273
14274         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14275
14276         if (exc || !mono_error_ok (&error)) {
14277                 mono_error_cleanup (&error);
14278                 return FALSE;
14279         } else
14280                 return *(MonoBoolean*)mono_object_unbox (res);
14281 }
14282
14283 /**
14284  * mono_reflection_type_get_type:
14285  * @reftype: the System.Type object
14286  *
14287  * Returns the MonoType* associated with the C# System.Type object @reftype.
14288  */
14289 MonoType*
14290 mono_reflection_type_get_type (MonoReflectionType *reftype)
14291 {
14292         g_assert (reftype);
14293
14294         MonoError error;
14295         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14296         mono_error_assert_ok (&error);
14297         return result;
14298 }
14299
14300 /**
14301  * mono_reflection_assembly_get_assembly:
14302  * @refassembly: the System.Reflection.Assembly object
14303  *
14304  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14305  */
14306 MonoAssembly*
14307 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14308 {
14309         g_assert (refassembly);
14310
14311         return refassembly->assembly;
14312 }
14313