[SRE] MonoError in mono_image_get_sighelper_token
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error);
167 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
168 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
169 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
170 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
171 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error);
172 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
173 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
174 static gboolean is_sre_array (MonoClass *klass);
175 static gboolean is_sre_byref (MonoClass *klass);
176 static gboolean is_sre_pointer (MonoClass *klass);
177 static gboolean is_sre_type_builder (MonoClass *klass);
178 static gboolean is_sre_method_builder (MonoClass *klass);
179 static gboolean is_sre_ctor_builder (MonoClass *klass);
180 static gboolean is_sre_field_builder (MonoClass *klass);
181 static gboolean is_sr_mono_method (MonoClass *klass);
182 static gboolean is_sr_mono_cmethod (MonoClass *klass);
183 static gboolean is_sr_mono_generic_method (MonoClass *klass);
184 static gboolean is_sr_mono_generic_cmethod (MonoClass *klass);
185 static gboolean is_sr_mono_field (MonoClass *klass);
186 static gboolean is_sr_mono_property (MonoClass *klass);
187 static gboolean is_sre_method_on_tb_inst (MonoClass *klass);
188 static gboolean is_sre_ctor_on_tb_inst (MonoClass *klass);
189
190 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
191 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
192 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
193
194 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
195 static void init_type_builder_generics (MonoObject *type);
196
197 #define RESOLVE_TYPE(type, error) do {                                  \
198         type = (MonoObject *)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type, error); \
199 } while (0)
200 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index, error) do {            \
201         MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
202         __type = mono_reflection_type_resolve_user_types (__type, error); \
203         if (mono_error_ok (error))                                      \
204                 mono_array_set (arr, MonoReflectionType*, index, __type); \
205 } while (0)
206
207 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
208
209 #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
210 #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
211
212 #if SIZEOF_VOID_P == 4
213 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
214 #else
215 #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
216 #endif
217
218 #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
219 #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
220
221 /* Class lazy loading functions */
222 static GENERATE_GET_CLASS_WITH_CACHE (mono_assembly, System.Reflection, MonoAssembly)
223 static GENERATE_GET_CLASS_WITH_CACHE (mono_module, System.Reflection, MonoModule)
224 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_method, System.Reflection, MonoGenericMethod);
225 static GENERATE_GET_CLASS_WITH_CACHE (mono_generic_cmethod, System.Reflection, MonoGenericCMethod);
226 static GENERATE_GET_CLASS_WITH_CACHE (mono_method, System.Reflection, MonoMethod);
227 static GENERATE_GET_CLASS_WITH_CACHE (mono_cmethod, System.Reflection, MonoCMethod);
228 static GENERATE_GET_CLASS_WITH_CACHE (mono_field, System.Reflection, MonoField);
229 static GENERATE_GET_CLASS_WITH_CACHE (mono_event, System.Reflection, MonoEvent);
230 static GENERATE_GET_CLASS_WITH_CACHE (mono_property, System.Reflection, MonoProperty);
231 static GENERATE_GET_CLASS_WITH_CACHE (mono_parameter_info, System.Reflection, MonoParameterInfo);
232 static GENERATE_GET_CLASS_WITH_CACHE (missing, System.Reflection, Missing);
233 static GENERATE_GET_CLASS_WITH_CACHE (method_body, System.Reflection, MethodBody);
234 static GENERATE_GET_CLASS_WITH_CACHE (local_variable_info, System.Reflection, LocalVariableInfo);
235 static GENERATE_GET_CLASS_WITH_CACHE (exception_handling_clause, System.Reflection, ExceptionHandlingClause);
236 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_typed_argument, System.Reflection, CustomAttributeTypedArgument);
237 static GENERATE_GET_CLASS_WITH_CACHE (custom_attribute_named_argument, System.Reflection, CustomAttributeNamedArgument);
238 static GENERATE_GET_CLASS_WITH_CACHE (type_builder, System.Reflection.Emit, TypeBuilder);
239 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
240 static GENERATE_GET_CLASS_WITH_CACHE (dbnull, System, DBNull);
241
242 // The dynamic images list is only needed to support the mempool reference tracking feature in checked-build.
243 static GPtrArray *dynamic_images;
244 static mono_mutex_t dynamic_images_mutex;
245
246 static inline void
247 dynamic_images_lock (void)
248 {
249         mono_os_mutex_lock (&dynamic_images_mutex);
250 }
251
252 static inline void
253 dynamic_images_unlock (void)
254 {
255         mono_os_mutex_unlock (&dynamic_images_mutex);
256 }
257
258 /**
259  * mono_find_dynamic_image_owner:
260  *
261  * Find the dynamic image, if any, which a given pointer is located in the memory of.
262  */
263 MonoImage *
264 mono_find_dynamic_image_owner (void *ptr)
265 {
266         MonoImage *owner = NULL;
267         int i;
268
269         dynamic_images_lock ();
270
271         if (dynamic_images)
272         {
273                 for (i = 0; !owner && i < dynamic_images->len; ++i) {
274                         MonoImage *image = (MonoImage *)g_ptr_array_index (dynamic_images, i);
275                         if (mono_mempool_contains_addr (image->mempool, ptr))
276                                 owner = image;
277                 }
278         }
279
280         dynamic_images_unlock ();
281
282         return owner;
283 }
284
285 void
286 mono_reflection_init (void)
287 {
288         mono_os_mutex_init (&dynamic_images_mutex);
289 }
290
291 static inline void
292 dynamic_image_lock (MonoDynamicImage *image)
293 {
294         MONO_PREPARE_BLOCKING;
295         mono_image_lock ((MonoImage*)image);
296         MONO_FINISH_BLOCKING;
297 }
298
299 static inline void
300 dynamic_image_unlock (MonoDynamicImage *image)
301 {
302         mono_image_unlock ((MonoImage*)image);
303 }
304
305 static void
306 register_dyn_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
307 {
308         MONO_REQ_GC_UNSAFE_MODE;
309
310         dynamic_image_lock (assembly);
311         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
312         dynamic_image_unlock (assembly);
313 }
314
315 static MonoObject*
316 lookup_dyn_token (MonoDynamicImage *assembly, guint32 token)
317 {
318         MONO_REQ_GC_UNSAFE_MODE;
319
320         MonoObject *obj;
321
322         dynamic_image_lock (assembly);
323         obj = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
324         dynamic_image_unlock (assembly);
325
326         return obj;
327 }
328
329 static void
330 sigbuffer_init (SigBuffer *buf, int size)
331 {
332         MONO_REQ_GC_NEUTRAL_MODE;
333
334         buf->buf = (char *)g_malloc (size);
335         buf->p = buf->buf;
336         buf->end = buf->buf + size;
337 }
338
339 static void
340 sigbuffer_make_room (SigBuffer *buf, int size)
341 {
342         MONO_REQ_GC_NEUTRAL_MODE;
343
344         if (buf->end - buf->p < size) {
345                 int new_size = buf->end - buf->buf + size + 32;
346                 char *p = (char *)g_realloc (buf->buf, new_size);
347                 size = buf->p - buf->buf;
348                 buf->buf = p;
349                 buf->p = p + size;
350                 buf->end = buf->buf + new_size;
351         }
352 }
353
354 static void
355 sigbuffer_add_value (SigBuffer *buf, guint32 val)
356 {
357         MONO_REQ_GC_NEUTRAL_MODE;
358
359         sigbuffer_make_room (buf, 6);
360         mono_metadata_encode_value (val, buf->p, &buf->p);
361 }
362
363 static void
364 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
365 {
366         MONO_REQ_GC_NEUTRAL_MODE;
367
368         sigbuffer_make_room (buf, 1);
369         buf->p [0] = val;
370         buf->p++;
371 }
372
373 static void
374 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
375 {
376         MONO_REQ_GC_NEUTRAL_MODE;
377
378         sigbuffer_make_room (buf, size);
379         memcpy (buf->p, p, size);
380         buf->p += size;
381 }
382
383 static void
384 sigbuffer_free (SigBuffer *buf)
385 {
386         MONO_REQ_GC_NEUTRAL_MODE;
387
388         g_free (buf->buf);
389 }
390
391 #ifndef DISABLE_REFLECTION_EMIT
392 /**
393  * mp_g_alloc:
394  *
395  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
396  * from the C heap.
397  */
398 static gpointer
399 image_g_malloc (MonoImage *image, guint size)
400 {
401         MONO_REQ_GC_NEUTRAL_MODE;
402
403         if (image)
404                 return mono_image_alloc (image, size);
405         else
406                 return g_malloc (size);
407 }
408 #endif /* !DISABLE_REFLECTION_EMIT */
409
410 /**
411  * image_g_alloc0:
412  *
413  * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
414  * from the C heap.
415  */
416 static gpointer
417 image_g_malloc0 (MonoImage *image, guint size)
418 {
419         MONO_REQ_GC_NEUTRAL_MODE;
420
421         if (image)
422                 return mono_image_alloc0 (image, size);
423         else
424                 return g_malloc0 (size);
425 }
426
427 /**
428  * image_g_free:
429  * @image: a MonoImage
430  * @ptr: pointer
431  *
432  * If @image is NULL, free @ptr, otherwise do nothing.
433  */
434 static void
435 image_g_free (MonoImage *image, gpointer ptr)
436 {
437         if (image == NULL)
438                 g_free (ptr);
439 }
440
441 #ifndef DISABLE_REFLECTION_EMIT
442 static char*
443 image_strdup (MonoImage *image, const char *s)
444 {
445         MONO_REQ_GC_NEUTRAL_MODE;
446
447         if (image)
448                 return mono_image_strdup (image, s);
449         else
450                 return g_strdup (s);
451 }
452 #endif
453
454 #define image_g_new(image,struct_type, n_structs)               \
455     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
456
457 #define image_g_new0(image,struct_type, n_structs)              \
458     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
459
460
461 static void
462 alloc_table (MonoDynamicTable *table, guint nrows)
463 {
464         MONO_REQ_GC_NEUTRAL_MODE;
465
466         table->rows = nrows;
467         g_assert (table->columns);
468         if (nrows + 1 >= table->alloc_rows) {
469                 while (nrows + 1 >= table->alloc_rows) {
470                         if (table->alloc_rows == 0)
471                                 table->alloc_rows = 16;
472                         else
473                                 table->alloc_rows *= 2;
474                 }
475
476                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
477         }
478 }
479
480 static void
481 make_room_in_stream (MonoDynamicStream *stream, int size)
482 {
483         MONO_REQ_GC_NEUTRAL_MODE;
484
485         if (size <= stream->alloc_size)
486                 return;
487         
488         while (stream->alloc_size <= size) {
489                 if (stream->alloc_size < 4096)
490                         stream->alloc_size = 4096;
491                 else
492                         stream->alloc_size *= 2;
493         }
494         
495         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
496 }
497
498 static guint32
499 string_heap_insert (MonoDynamicStream *sh, const char *str)
500 {
501         MONO_REQ_GC_NEUTRAL_MODE;
502
503         guint32 idx;
504         guint32 len;
505         gpointer oldkey, oldval;
506
507         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
508                 return GPOINTER_TO_UINT (oldval);
509
510         len = strlen (str) + 1;
511         idx = sh->index;
512         
513         make_room_in_stream (sh, idx + len);
514
515         /*
516          * We strdup the string even if we already copy them in sh->data
517          * so that the string pointers in the hash remain valid even if
518          * we need to realloc sh->data. We may want to avoid that later.
519          */
520         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
521         memcpy (sh->data + idx, str, len);
522         sh->index += len;
523         return idx;
524 }
525
526 static guint32
527 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
528 {
529         MONO_REQ_GC_UNSAFE_MODE;
530
531         char *name = mono_string_to_utf8 (str);
532         guint32 idx;
533         idx = string_heap_insert (sh, name);
534         g_free (name);
535         return idx;
536 }
537
538 #ifndef DISABLE_REFLECTION_EMIT
539 static void
540 string_heap_init (MonoDynamicStream *sh)
541 {
542         MONO_REQ_GC_NEUTRAL_MODE;
543
544         sh->index = 0;
545         sh->alloc_size = 4096;
546         sh->data = (char *)g_malloc (4096);
547         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
548         string_heap_insert (sh, "");
549 }
550 #endif
551
552 static guint32
553 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
554 {
555         MONO_REQ_GC_NEUTRAL_MODE;
556
557         guint32 idx;
558         
559         make_room_in_stream (stream, stream->index + len);
560         memcpy (stream->data + stream->index, data, len);
561         idx = stream->index;
562         stream->index += len;
563         /* 
564          * align index? Not without adding an additional param that controls it since
565          * we may store a blob value in pieces.
566          */
567         return idx;
568 }
569
570 static guint32
571 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         guint32 idx;
576         
577         make_room_in_stream (stream, stream->index + len);
578         memset (stream->data + stream->index, 0, len);
579         idx = stream->index;
580         stream->index += len;
581         return idx;
582 }
583
584 static void
585 stream_data_align (MonoDynamicStream *stream)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         char buf [4] = {0};
590         guint32 count = stream->index % 4;
591
592         /* we assume the stream data will be aligned */
593         if (count)
594                 mono_image_add_stream_data (stream, buf, 4 - count);
595 }
596
597 #ifndef DISABLE_REFLECTION_EMIT
598 static int
599 mono_blob_entry_hash (const char* str)
600 {
601         MONO_REQ_GC_NEUTRAL_MODE;
602
603         guint len, h;
604         const char *end;
605         len = mono_metadata_decode_blob_size (str, &str);
606         if (len > 0) {
607                 end = str + len;
608                 h = *str;
609                 for (str += 1; str < end; str++)
610                         h = (h << 5) - h + *str;
611                 return h;
612         } else {
613                 return 0;
614         }
615 }
616
617 static gboolean
618 mono_blob_entry_equal (const char *str1, const char *str2) {
619         MONO_REQ_GC_NEUTRAL_MODE;
620
621         int len, len2;
622         const char *end1;
623         const char *end2;
624         len = mono_metadata_decode_blob_size (str1, &end1);
625         len2 = mono_metadata_decode_blob_size (str2, &end2);
626         if (len != len2)
627                 return 0;
628         return memcmp (end1, end2, len) == 0;
629 }
630 #endif
631 static guint32
632 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
633 {
634         MONO_REQ_GC_NEUTRAL_MODE;
635
636         guint32 idx;
637         char *copy;
638         gpointer oldkey, oldval;
639
640         copy = (char *)g_malloc (s1+s2);
641         memcpy (copy, b1, s1);
642         memcpy (copy + s1, b2, s2);
643         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
644                 g_free (copy);
645                 idx = GPOINTER_TO_UINT (oldval);
646         } else {
647                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
648                 mono_image_add_stream_data (&assembly->blob, b2, s2);
649                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
650         }
651         return idx;
652 }
653
654 static guint32
655 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
656 {
657         MONO_REQ_GC_NEUTRAL_MODE;
658
659         char blob_size [8];
660         char *b = blob_size;
661         guint32 size = buf->p - buf->buf;
662         /* store length */
663         g_assert (size <= (buf->end - buf->buf));
664         mono_metadata_encode_value (size, b, &b);
665         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
666 }
667
668 /*
669  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
670  * dest may be misaligned.
671  */
672 static void
673 swap_with_size (char *dest, const char* val, int len, int nelem) {
674         MONO_REQ_GC_NEUTRAL_MODE;
675 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
676         int elem;
677
678         for (elem = 0; elem < nelem; ++elem) {
679                 switch (len) {
680                 case 1:
681                         *dest = *val;
682                         break;
683                 case 2:
684                         dest [0] = val [1];
685                         dest [1] = val [0];
686                         break;
687                 case 4:
688                         dest [0] = val [3];
689                         dest [1] = val [2];
690                         dest [2] = val [1];
691                         dest [3] = val [0];
692                         break;
693                 case 8:
694                         dest [0] = val [7];
695                         dest [1] = val [6];
696                         dest [2] = val [5];
697                         dest [3] = val [4];
698                         dest [4] = val [3];
699                         dest [5] = val [2];
700                         dest [6] = val [1];
701                         dest [7] = val [0];
702                         break;
703                 default:
704                         g_assert_not_reached ();
705                 }
706                 dest += len;
707                 val += len;
708         }
709 #else
710         memcpy (dest, val, len * nelem);
711 #endif
712 }
713
714 static guint32
715 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
716 {
717         MONO_REQ_GC_UNSAFE_MODE;
718         
719         char blob_size [64];
720         char *b = blob_size;
721         guint32 idx = 0, len;
722
723         len = str->length * 2;
724         mono_metadata_encode_value (len, b, &b);
725 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
726         {
727                 char *swapped = g_malloc (2 * mono_string_length (str));
728                 const char *p = (const char*)mono_string_chars (str);
729
730                 swap_with_size (swapped, p, 2, mono_string_length (str));
731                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
732                 g_free (swapped);
733         }
734 #else
735         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
736 #endif
737         return idx;
738 }
739
740 #ifndef DISABLE_REFLECTION_EMIT
741 static MonoClass *
742 default_class_from_mono_type (MonoType *type)
743 {
744         MONO_REQ_GC_NEUTRAL_MODE;
745
746         switch (type->type) {
747         case MONO_TYPE_OBJECT:
748                 return mono_defaults.object_class;
749         case MONO_TYPE_VOID:
750                 return mono_defaults.void_class;
751         case MONO_TYPE_BOOLEAN:
752                 return mono_defaults.boolean_class;
753         case MONO_TYPE_CHAR:
754                 return mono_defaults.char_class;
755         case MONO_TYPE_I1:
756                 return mono_defaults.sbyte_class;
757         case MONO_TYPE_U1:
758                 return mono_defaults.byte_class;
759         case MONO_TYPE_I2:
760                 return mono_defaults.int16_class;
761         case MONO_TYPE_U2:
762                 return mono_defaults.uint16_class;
763         case MONO_TYPE_I4:
764                 return mono_defaults.int32_class;
765         case MONO_TYPE_U4:
766                 return mono_defaults.uint32_class;
767         case MONO_TYPE_I:
768                 return mono_defaults.int_class;
769         case MONO_TYPE_U:
770                 return mono_defaults.uint_class;
771         case MONO_TYPE_I8:
772                 return mono_defaults.int64_class;
773         case MONO_TYPE_U8:
774                 return mono_defaults.uint64_class;
775         case MONO_TYPE_R4:
776                 return mono_defaults.single_class;
777         case MONO_TYPE_R8:
778                 return mono_defaults.double_class;
779         case MONO_TYPE_STRING:
780                 return mono_defaults.string_class;
781         default:
782                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
783                 g_assert_not_reached ();
784         }
785         
786         return NULL;
787 }
788 #endif
789
790 /*
791  * mono_class_get_ref_info:
792  *
793  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
794  */
795 gpointer
796 mono_class_get_ref_info (MonoClass *klass)
797 {
798         MONO_REQ_GC_UNSAFE_MODE;
799
800         if (klass->ref_info_handle == 0)
801                 return NULL;
802         else
803                 return mono_gchandle_get_target (klass->ref_info_handle);
804 }
805
806 void
807 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
808 {
809         MONO_REQ_GC_UNSAFE_MODE;
810
811         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
812         g_assert (klass->ref_info_handle != 0);
813 }
814
815 void
816 mono_class_free_ref_info (MonoClass *klass)
817 {
818         MONO_REQ_GC_NEUTRAL_MODE;
819
820         if (klass->ref_info_handle) {
821                 mono_gchandle_free (klass->ref_info_handle);
822                 klass->ref_info_handle = 0;
823         }
824 }
825
826 static void
827 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
828 {
829         MONO_REQ_GC_NEUTRAL_MODE;
830
831         int i;
832         MonoGenericInst *class_inst;
833         MonoClass *klass;
834
835         g_assert (gclass);
836
837         class_inst = gclass->context.class_inst;
838
839         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
840         klass = gclass->container_class;
841         sigbuffer_add_value (buf, klass->byval_arg.type);
842         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
843
844         sigbuffer_add_value (buf, class_inst->type_argc);
845         for (i = 0; i < class_inst->type_argc; ++i)
846                 encode_type (assembly, class_inst->type_argv [i], buf);
847
848 }
849
850 static void
851 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
852 {
853         MONO_REQ_GC_NEUTRAL_MODE;
854
855         if (!type) {
856                 g_assert_not_reached ();
857                 return;
858         }
859                 
860         if (type->byref)
861                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
862
863         switch (type->type){
864         case MONO_TYPE_VOID:
865         case MONO_TYPE_BOOLEAN:
866         case MONO_TYPE_CHAR:
867         case MONO_TYPE_I1:
868         case MONO_TYPE_U1:
869         case MONO_TYPE_I2:
870         case MONO_TYPE_U2:
871         case MONO_TYPE_I4:
872         case MONO_TYPE_U4:
873         case MONO_TYPE_I8:
874         case MONO_TYPE_U8:
875         case MONO_TYPE_R4:
876         case MONO_TYPE_R8:
877         case MONO_TYPE_I:
878         case MONO_TYPE_U:
879         case MONO_TYPE_STRING:
880         case MONO_TYPE_OBJECT:
881         case MONO_TYPE_TYPEDBYREF:
882                 sigbuffer_add_value (buf, type->type);
883                 break;
884         case MONO_TYPE_PTR:
885                 sigbuffer_add_value (buf, type->type);
886                 encode_type (assembly, type->data.type, buf);
887                 break;
888         case MONO_TYPE_SZARRAY:
889                 sigbuffer_add_value (buf, type->type);
890                 encode_type (assembly, &type->data.klass->byval_arg, buf);
891                 break;
892         case MONO_TYPE_VALUETYPE:
893         case MONO_TYPE_CLASS: {
894                 MonoClass *k = mono_class_from_mono_type (type);
895
896                 if (k->generic_container) {
897                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
898                         encode_generic_class (assembly, gclass, buf);
899                 } else {
900                         /*
901                          * Make sure we use the correct type.
902                          */
903                         sigbuffer_add_value (buf, k->byval_arg.type);
904                         /*
905                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
906                          * otherwise two typerefs could point to the same type, leading to
907                          * verification errors.
908                          */
909                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
910                 }
911                 break;
912         }
913         case MONO_TYPE_ARRAY:
914                 sigbuffer_add_value (buf, type->type);
915                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
916                 sigbuffer_add_value (buf, type->data.array->rank);
917                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
918                 sigbuffer_add_value (buf, 0);
919                 break;
920         case MONO_TYPE_GENERICINST:
921                 encode_generic_class (assembly, type->data.generic_class, buf);
922                 break;
923         case MONO_TYPE_VAR:
924         case MONO_TYPE_MVAR:
925                 sigbuffer_add_value (buf, type->type);
926                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
927                 break;
928         default:
929                 g_error ("need to encode type %x", type->type);
930         }
931 }
932
933 static void
934 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
935 {
936         MONO_REQ_GC_UNSAFE_MODE;
937
938         mono_error_init (error);
939
940         if (!type) {
941                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
942                 return;
943         }
944
945         MonoType *t = mono_reflection_type_get_handle (type, error);
946         return_if_nok (error);
947         encode_type (assembly, t, buf);
948 }
949
950 static void
951 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
952 {
953         MONO_REQ_GC_UNSAFE_MODE;
954
955         int i;
956
957         mono_error_init (error);
958
959         if (modreq) {
960                 for (i = 0; i < mono_array_length (modreq); ++i) {
961                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
962                         return_if_nok (error);
963                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
964                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
965                 }
966         }
967         if (modopt) {
968                 for (i = 0; i < mono_array_length (modopt); ++i) {
969                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
970                         return_if_nok (error);
971                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
972                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
973                 }
974         }
975 }
976
977 #ifndef DISABLE_REFLECTION_EMIT
978 static guint32
979 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
980 {
981         MONO_REQ_GC_UNSAFE_MODE;
982
983         SigBuffer buf;
984         int i;
985         guint32 nparams =  sig->param_count;
986         guint32 idx;
987
988         if (!assembly->save)
989                 return 0;
990
991         sigbuffer_init (&buf, 32);
992         /*
993          * FIXME: vararg, explicit_this, differenc call_conv values...
994          */
995         idx = sig->call_convention;
996         if (sig->hasthis)
997                 idx |= 0x20; /* hasthis */
998         if (sig->generic_param_count)
999                 idx |= 0x10; /* generic */
1000         sigbuffer_add_byte (&buf, idx);
1001         if (sig->generic_param_count)
1002                 sigbuffer_add_value (&buf, sig->generic_param_count);
1003         sigbuffer_add_value (&buf, nparams);
1004         encode_type (assembly, sig->ret, &buf);
1005         for (i = 0; i < nparams; ++i) {
1006                 if (i == sig->sentinelpos)
1007                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1008                 encode_type (assembly, sig->params [i], &buf);
1009         }
1010         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1011         sigbuffer_free (&buf);
1012         return idx;
1013 }
1014 #endif
1015
1016 static guint32
1017 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1018 {
1019         MONO_REQ_GC_UNSAFE_MODE;
1020
1021         mono_error_init (error);
1022
1023         /*
1024          * FIXME: reuse code from method_encode_signature().
1025          */
1026         SigBuffer buf;
1027         int i;
1028         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1029         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1030         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1031         guint32 idx;
1032
1033         sigbuffer_init (&buf, 32);
1034         /* LAMESPEC: all the call conv spec is foobared */
1035         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1036         if (mb->call_conv & 2)
1037                 idx |= 0x5; /* vararg */
1038         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1039                 idx |= 0x20; /* hasthis */
1040         if (ngparams)
1041                 idx |= 0x10; /* generic */
1042         sigbuffer_add_byte (&buf, idx);
1043         if (ngparams)
1044                 sigbuffer_add_value (&buf, ngparams);
1045         sigbuffer_add_value (&buf, nparams + notypes);
1046         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
1047         if (!is_ok (error))
1048                 goto leave;
1049         encode_reflection_type (assembly, mb->rtype, &buf, error);
1050         if (!is_ok (error))
1051                 goto leave;
1052         for (i = 0; i < nparams; ++i) {
1053                 MonoArray *modreq = NULL;
1054                 MonoArray *modopt = NULL;
1055                 MonoReflectionType *pt;
1056
1057                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1058                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1059                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1060                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1061                 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
1062                 if (!is_ok (error))
1063                         goto leave;
1064                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1065                 encode_reflection_type (assembly, pt, &buf, error);
1066                 if (!is_ok (error))
1067                         goto leave;
1068         }
1069         if (notypes)
1070                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1071         for (i = 0; i < notypes; ++i) {
1072                 MonoReflectionType *pt;
1073
1074                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1075                 encode_reflection_type (assembly, pt, &buf, error);
1076                 if (!is_ok (error))
1077                         goto leave;
1078         }
1079
1080         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1081 leave:
1082         sigbuffer_free (&buf);
1083         return idx;
1084 }
1085
1086 static guint32
1087 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
1088 {
1089         MONO_REQ_GC_UNSAFE_MODE;
1090
1091         mono_error_init (error);
1092
1093         MonoDynamicTable *table;
1094         guint32 *values;
1095         guint32 idx, sig_idx;
1096         guint nl = mono_array_length (ilgen->locals);
1097         SigBuffer buf;
1098         int i;
1099
1100         sigbuffer_init (&buf, 32);
1101         sigbuffer_add_value (&buf, 0x07);
1102         sigbuffer_add_value (&buf, nl);
1103         for (i = 0; i < nl; ++i) {
1104                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1105                 
1106                 if (lb->is_pinned)
1107                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1108                 
1109                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
1110                 if (!is_ok (error)) {
1111                         sigbuffer_free (&buf);
1112                         return 0;
1113                 }
1114         }
1115         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1116         sigbuffer_free (&buf);
1117
1118         if (assembly->standalonesig_cache == NULL)
1119                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1120         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1121         if (idx)
1122                 return idx;
1123
1124         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1125         idx = table->next_idx ++;
1126         table->rows ++;
1127         alloc_table (table, table->rows);
1128         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1129
1130         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1131
1132         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1133
1134         return idx;
1135 }
1136
1137 static guint32
1138 method_count_clauses (MonoReflectionILGen *ilgen)
1139 {
1140         MONO_REQ_GC_UNSAFE_MODE;
1141
1142         guint32 num_clauses = 0;
1143         int i;
1144
1145         MonoILExceptionInfo *ex_info;
1146         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1147                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1148                 if (ex_info->handlers)
1149                         num_clauses += mono_array_length (ex_info->handlers);
1150                 else
1151                         num_clauses++;
1152         }
1153
1154         return num_clauses;
1155 }
1156
1157 #ifndef DISABLE_REFLECTION_EMIT
1158 static MonoExceptionClause*
1159 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
1160 {
1161         MONO_REQ_GC_UNSAFE_MODE;
1162
1163         mono_error_init (error);
1164
1165         MonoExceptionClause *clauses;
1166         MonoExceptionClause *clause;
1167         MonoILExceptionInfo *ex_info;
1168         MonoILExceptionBlock *ex_block;
1169         guint32 finally_start;
1170         int i, j, clause_index;;
1171
1172         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1173
1174         clause_index = 0;
1175         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1176                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1177                 finally_start = ex_info->start + ex_info->len;
1178                 if (!ex_info->handlers)
1179                         continue;
1180                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1181                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1182                         clause = &(clauses [clause_index]);
1183
1184                         clause->flags = ex_block->type;
1185                         clause->try_offset = ex_info->start;
1186
1187                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1188                                 clause->try_len = finally_start - ex_info->start;
1189                         else
1190                                 clause->try_len = ex_info->len;
1191                         clause->handler_offset = ex_block->start;
1192                         clause->handler_len = ex_block->len;
1193                         if (ex_block->extype) {
1194                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1195
1196                                 if (!is_ok (error)) {
1197                                         image_g_free (image, clauses);
1198                                         return NULL;
1199                                 }
1200                                 clause->data.catch_class = mono_class_from_mono_type (extype);
1201                         } else {
1202                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1203                                         clause->data.filter_offset = ex_block->filter_offset;
1204                                 else
1205                                         clause->data.filter_offset = 0;
1206                         }
1207                         finally_start = ex_block->start + ex_block->len;
1208
1209                         clause_index ++;
1210                 }
1211         }
1212
1213         return clauses;
1214 }
1215 #endif /* !DISABLE_REFLECTION_EMIT */
1216
1217 /**
1218  * method_encode_code:
1219  *
1220  * @assembly the assembly
1221  * @mb the managed MethodBuilder
1222  * @error set on error
1223  *
1224  * Note that the return value is not sensible if @error is set.
1225  */
1226 static guint32
1227 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1228 {
1229         MONO_REQ_GC_UNSAFE_MODE;
1230
1231         char flags = 0;
1232         guint32 idx;
1233         guint32 code_size;
1234         gint32 max_stack, i;
1235         gint32 num_locals = 0;
1236         gint32 num_exception = 0;
1237         gint maybe_small;
1238         guint32 fat_flags;
1239         char fat_header [12];
1240         guint32 int_value;
1241         guint16 short_value;
1242         guint32 local_sig = 0;
1243         guint32 header_size = 12;
1244         MonoArray *code;
1245
1246         mono_error_init (error);
1247
1248         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1249                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1250                 return 0;
1251
1252         /*if (mb->name)
1253                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1254         if (mb->ilgen) {
1255                 code = mb->ilgen->code;
1256                 code_size = mb->ilgen->code_len;
1257                 max_stack = mb->ilgen->max_stack;
1258                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1259                 if (mb->ilgen->ex_handlers)
1260                         num_exception = method_count_clauses (mb->ilgen);
1261         } else {
1262                 code = mb->code;
1263                 if (code == NULL){
1264                         char *name = mono_string_to_utf8 (mb->name);
1265                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1266                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1267                         g_free (str);
1268                         g_free (name);
1269                         return 0;
1270                 }
1271
1272                 code_size = mono_array_length (code);
1273                 max_stack = 8; /* we probably need to run a verifier on the code... */
1274         }
1275
1276         stream_data_align (&assembly->code);
1277
1278         /* check for exceptions, maxstack, locals */
1279         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1280         if (maybe_small) {
1281                 if (code_size < 64 && !(code_size & 1)) {
1282                         flags = (code_size << 2) | 0x2;
1283                 } else if (code_size < 32 && (code_size & 1)) {
1284                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1285                 } else {
1286                         goto fat_header;
1287                 }
1288                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1289                 /* add to the fixup todo list */
1290                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1291                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1292                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1293                 return assembly->text_rva + idx;
1294         } 
1295 fat_header:
1296         if (num_locals) {
1297                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen, error);
1298                 return_val_if_nok (error, 0);
1299         }
1300         /* 
1301          * FIXME: need to set also the header size in fat_flags.
1302          * (and more sects and init locals flags)
1303          */
1304         fat_flags =  0x03;
1305         if (num_exception)
1306                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1307         if (mb->init_locals)
1308                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1309         fat_header [0] = fat_flags;
1310         fat_header [1] = (header_size / 4 ) << 4;
1311         short_value = GUINT16_TO_LE (max_stack);
1312         memcpy (fat_header + 2, &short_value, 2);
1313         int_value = GUINT32_TO_LE (code_size);
1314         memcpy (fat_header + 4, &int_value, 4);
1315         int_value = GUINT32_TO_LE (local_sig);
1316         memcpy (fat_header + 8, &int_value, 4);
1317         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1318         /* add to the fixup todo list */
1319         if (mb->ilgen && mb->ilgen->num_token_fixups)
1320                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1321         
1322         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1323         if (num_exception) {
1324                 unsigned char sheader [4];
1325                 MonoILExceptionInfo * ex_info;
1326                 MonoILExceptionBlock * ex_block;
1327                 int j;
1328
1329                 stream_data_align (&assembly->code);
1330                 /* always use fat format for now */
1331                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1332                 num_exception *= 6 * sizeof (guint32);
1333                 num_exception += 4; /* include the size of the header */
1334                 sheader [1] = num_exception & 0xff;
1335                 sheader [2] = (num_exception >> 8) & 0xff;
1336                 sheader [3] = (num_exception >> 16) & 0xff;
1337                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1338                 /* fat header, so we are already aligned */
1339                 /* reverse order */
1340                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1341                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1342                         if (ex_info->handlers) {
1343                                 int finally_start = ex_info->start + ex_info->len;
1344                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1345                                         guint32 val;
1346                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1347                                         /* the flags */
1348                                         val = GUINT32_TO_LE (ex_block->type);
1349                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1350                                         /* try offset */
1351                                         val = GUINT32_TO_LE (ex_info->start);
1352                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1353                                         /* need fault, too, probably */
1354                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1355                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1356                                         else
1357                                                 val = GUINT32_TO_LE (ex_info->len);
1358                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1359                                         /* handler offset */
1360                                         val = GUINT32_TO_LE (ex_block->start);
1361                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1362                                         /* handler len */
1363                                         val = GUINT32_TO_LE (ex_block->len);
1364                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1365                                         finally_start = ex_block->start + ex_block->len;
1366                                         if (ex_block->extype) {
1367                                                 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
1368                                                 return_val_if_nok (error, 0);
1369
1370                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, extype));
1371                                         } else {
1372                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1373                                                         val = ex_block->filter_offset;
1374                                                 else
1375                                                         val = 0;
1376                                         }
1377                                         val = GUINT32_TO_LE (val);
1378                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1379                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1380                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1381                                 }
1382                         } else {
1383                                 g_error ("No clauses for ex info block %d", i);
1384                         }
1385                 }
1386         }
1387         return assembly->text_rva + idx;
1388 }
1389
1390 static guint32
1391 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1392 {
1393         MONO_REQ_GC_NEUTRAL_MODE;
1394
1395         int i;
1396         MonoDynamicTable *table;
1397         guint32 *values;
1398         
1399         table = &assembly->tables [table_idx];
1400
1401         g_assert (col < table->columns);
1402
1403         values = table->values + table->columns;
1404         for (i = 1; i <= table->rows; ++i) {
1405                 if (values [col] == token)
1406                         return i;
1407                 values += table->columns;
1408         }
1409         return 0;
1410 }
1411
1412 /*
1413  * LOCKING: Acquires the loader lock. 
1414  */
1415 static MonoCustomAttrInfo*
1416 lookup_custom_attr (MonoImage *image, gpointer member)
1417 {
1418         MONO_REQ_GC_NEUTRAL_MODE;
1419
1420         MonoCustomAttrInfo* res;
1421
1422         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1423
1424         if (!res)
1425                 return NULL;
1426
1427         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1428         res->cached = 0;
1429         return res;
1430 }
1431
1432 static gboolean
1433 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1434 {
1435         MONO_REQ_GC_UNSAFE_MODE;
1436
1437         /* FIXME: Need to do more checks */
1438         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1439                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1440
1441                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1442                         return FALSE;
1443         }
1444
1445         return TRUE;
1446 }
1447
1448 static MonoCustomAttrInfo*
1449 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1450 {
1451         MONO_REQ_GC_UNSAFE_MODE;
1452
1453         int i, index, count, not_visible;
1454         MonoCustomAttrInfo *ainfo;
1455         MonoReflectionCustomAttr *cattr;
1456
1457         if (!cattrs)
1458                 return NULL;
1459         /* FIXME: check in assembly the Run flag is set */
1460
1461         count = mono_array_length (cattrs);
1462
1463         /* Skip nonpublic attributes since MS.NET seems to do the same */
1464         /* FIXME: This needs to be done more globally */
1465         not_visible = 0;
1466         for (i = 0; i < count; ++i) {
1467                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1468                 if (!custom_attr_visible (image, cattr))
1469                         not_visible ++;
1470         }
1471         count -= not_visible;
1472
1473         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1474
1475         ainfo->image = image;
1476         ainfo->num_attrs = count;
1477         ainfo->cached = alloc_img != NULL;
1478         index = 0;
1479         for (i = 0; i < count; ++i) {
1480                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1481                 if (custom_attr_visible (image, cattr)) {
1482                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1483                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1484                         ainfo->attrs [index].ctor = cattr->ctor->method;
1485                         ainfo->attrs [index].data = saved;
1486                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1487                         index ++;
1488                 }
1489         }
1490
1491         return ainfo;
1492 }
1493
1494 #ifndef DISABLE_REFLECTION_EMIT
1495 /*
1496  * LOCKING: Acquires the loader lock. 
1497  */
1498 static void
1499 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1500 {
1501         MONO_REQ_GC_UNSAFE_MODE;
1502
1503         MonoCustomAttrInfo *ainfo, *tmp;
1504
1505         if (!cattrs || !mono_array_length (cattrs))
1506                 return;
1507
1508         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1509
1510         mono_loader_lock ();
1511         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1512         if (tmp)
1513                 mono_custom_attrs_free (tmp);
1514         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1515         mono_loader_unlock ();
1516
1517 }
1518 #endif
1519
1520 void
1521 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1522 {
1523         MONO_REQ_GC_NEUTRAL_MODE;
1524
1525         if (ainfo && !ainfo->cached)
1526                 g_free (ainfo);
1527 }
1528
1529 /*
1530  * idx is the table index of the object
1531  * type is one of MONO_CUSTOM_ATTR_*
1532  */
1533 static gboolean
1534 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1535 {
1536         MONO_REQ_GC_UNSAFE_MODE;
1537
1538         MonoDynamicTable *table;
1539         MonoReflectionCustomAttr *cattr;
1540         guint32 *values;
1541         guint32 count, i, token;
1542         char blob_size [6];
1543         char *p = blob_size;
1544         
1545         mono_error_init (error);
1546
1547         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1548         if (!cattrs)
1549                 return TRUE;
1550         count = mono_array_length (cattrs);
1551         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1552         table->rows += count;
1553         alloc_table (table, table->rows);
1554         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1555         idx <<= MONO_CUSTOM_ATTR_BITS;
1556         idx |= type;
1557         for (i = 0; i < count; ++i) {
1558                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1559                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1560                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1561                 if (!mono_error_ok (error)) goto fail;
1562                 type = mono_metadata_token_index (token);
1563                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1564                 switch (mono_metadata_token_table (token)) {
1565                 case MONO_TABLE_METHOD:
1566                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1567                         /*
1568                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1569                          * method, not the one returned by mono_image_create_token ().
1570                          */
1571                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1572                         break;
1573                 case MONO_TABLE_MEMBERREF:
1574                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1575                         break;
1576                 default:
1577                         g_warning ("got wrong token in custom attr");
1578                         continue;
1579                 }
1580                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1581                 p = blob_size;
1582                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1583                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1584                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1585                 values += MONO_CUSTOM_ATTR_SIZE;
1586                 ++table->next_idx;
1587         }
1588
1589         return TRUE;
1590
1591 fail:
1592         return FALSE;
1593 }
1594
1595 static void
1596 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1597 {
1598         MONO_REQ_GC_UNSAFE_MODE;
1599
1600         MonoDynamicTable *table;
1601         guint32 *values;
1602         guint32 count, i, idx;
1603         MonoReflectionPermissionSet *perm;
1604
1605         if (!permissions)
1606                 return;
1607
1608         count = mono_array_length (permissions);
1609         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1610         table->rows += count;
1611         alloc_table (table, table->rows);
1612
1613         for (i = 0; i < mono_array_length (permissions); ++i) {
1614                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1615
1616                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1617
1618                 idx = mono_metadata_token_index (parent_token);
1619                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1620                 switch (mono_metadata_token_table (parent_token)) {
1621                 case MONO_TABLE_TYPEDEF:
1622                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1623                         break;
1624                 case MONO_TABLE_METHOD:
1625                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1626                         break;
1627                 case MONO_TABLE_ASSEMBLY:
1628                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1629                         break;
1630                 default:
1631                         g_assert_not_reached ();
1632                 }
1633
1634                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1635                 values [MONO_DECL_SECURITY_PARENT] = idx;
1636                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1637
1638                 ++table->next_idx;
1639         }
1640 }
1641
1642 /*
1643  * Fill in the MethodDef and ParamDef tables for a method.
1644  * This is used for both normal methods and constructors.
1645  */
1646 static gboolean
1647 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1648 {
1649         MONO_REQ_GC_UNSAFE_MODE;
1650
1651         MonoDynamicTable *table;
1652         guint32 *values;
1653         guint i, count;
1654
1655         mono_error_init (error);
1656
1657         /* room in this table is already allocated */
1658         table = &assembly->tables [MONO_TABLE_METHOD];
1659         *mb->table_idx = table->next_idx ++;
1660         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1661         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1662         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1663         values [MONO_METHOD_FLAGS] = mb->attrs;
1664         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1665         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb, error);
1666         return_val_if_nok (error, FALSE);
1667         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1668         return_val_if_nok (error, FALSE);
1669
1670         table = &assembly->tables [MONO_TABLE_PARAM];
1671         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1672
1673         mono_image_add_decl_security (assembly, 
1674                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1675
1676         if (mb->pinfo) {
1677                 MonoDynamicTable *mtable;
1678                 guint32 *mvalues;
1679                 
1680                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1681                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1682                 
1683                 count = 0;
1684                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1685                         if (mono_array_get (mb->pinfo, gpointer, i))
1686                                 count++;
1687                 }
1688                 table->rows += count;
1689                 alloc_table (table, table->rows);
1690                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1691                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1692                         MonoReflectionParamBuilder *pb;
1693                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1694                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1695                                 values [MONO_PARAM_SEQUENCE] = i;
1696                                 if (pb->name != NULL) {
1697                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1698                                 } else {
1699                                         values [MONO_PARAM_NAME] = 0;
1700                                 }
1701                                 values += MONO_PARAM_SIZE;
1702                                 if (pb->marshal_info) {
1703                                         mtable->rows++;
1704                                         alloc_table (mtable, mtable->rows);
1705                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1706                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1707                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info, error);
1708                                         return_val_if_nok (error, FALSE);
1709                                 }
1710                                 pb->table_idx = table->next_idx++;
1711                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1712                                         guint32 field_type = 0;
1713                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1714                                         mtable->rows ++;
1715                                         alloc_table (mtable, mtable->rows);
1716                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1717                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1718                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1719                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1720                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1721                                 }
1722                         }
1723                 }
1724         }
1725
1726         return TRUE;
1727 }
1728
1729 #ifndef DISABLE_REFLECTION_EMIT
1730 static gboolean
1731 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1732 {
1733         MONO_REQ_GC_UNSAFE_MODE;
1734
1735         mono_error_init (error);
1736         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1737
1738         rmb->ilgen = mb->ilgen;
1739         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1740         return_val_if_nok (error, FALSE);
1741         rmb->parameters = mb->parameters;
1742         rmb->generic_params = mb->generic_params;
1743         rmb->generic_container = mb->generic_container;
1744         rmb->opt_types = NULL;
1745         rmb->pinfo = mb->pinfo;
1746         rmb->attrs = mb->attrs;
1747         rmb->iattrs = mb->iattrs;
1748         rmb->call_conv = mb->call_conv;
1749         rmb->code = mb->code;
1750         rmb->type = mb->type;
1751         rmb->name = mb->name;
1752         rmb->table_idx = &mb->table_idx;
1753         rmb->init_locals = mb->init_locals;
1754         rmb->skip_visibility = FALSE;
1755         rmb->return_modreq = mb->return_modreq;
1756         rmb->return_modopt = mb->return_modopt;
1757         rmb->param_modreq = mb->param_modreq;
1758         rmb->param_modopt = mb->param_modopt;
1759         rmb->permissions = mb->permissions;
1760         rmb->mhandle = mb->mhandle;
1761         rmb->nrefs = 0;
1762         rmb->refs = NULL;
1763
1764         if (mb->dll) {
1765                 rmb->charset = mb->charset;
1766                 rmb->extra_flags = mb->extra_flags;
1767                 rmb->native_cc = mb->native_cc;
1768                 rmb->dllentry = mb->dllentry;
1769                 rmb->dll = mb->dll;
1770         }
1771
1772         return TRUE;
1773 }
1774
1775 static gboolean
1776 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1777 {
1778         MONO_REQ_GC_UNSAFE_MODE;
1779
1780         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1781
1782         mono_error_init (error);
1783
1784         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1785
1786         rmb->ilgen = mb->ilgen;
1787         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1788         return_val_if_nok (error, FALSE);
1789         rmb->parameters = mb->parameters;
1790         rmb->generic_params = NULL;
1791         rmb->generic_container = NULL;
1792         rmb->opt_types = NULL;
1793         rmb->pinfo = mb->pinfo;
1794         rmb->attrs = mb->attrs;
1795         rmb->iattrs = mb->iattrs;
1796         rmb->call_conv = mb->call_conv;
1797         rmb->code = NULL;
1798         rmb->type = mb->type;
1799         rmb->name = mono_string_new (mono_domain_get (), name);
1800         rmb->table_idx = &mb->table_idx;
1801         rmb->init_locals = mb->init_locals;
1802         rmb->skip_visibility = FALSE;
1803         rmb->return_modreq = NULL;
1804         rmb->return_modopt = NULL;
1805         rmb->param_modreq = mb->param_modreq;
1806         rmb->param_modopt = mb->param_modopt;
1807         rmb->permissions = mb->permissions;
1808         rmb->mhandle = mb->mhandle;
1809         rmb->nrefs = 0;
1810         rmb->refs = NULL;
1811
1812         return TRUE;
1813 }
1814
1815 static void
1816 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1817 {
1818         MONO_REQ_GC_UNSAFE_MODE;
1819
1820         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1821
1822         rmb->ilgen = mb->ilgen;
1823         rmb->rtype = mb->rtype;
1824         rmb->parameters = mb->parameters;
1825         rmb->generic_params = NULL;
1826         rmb->generic_container = NULL;
1827         rmb->opt_types = NULL;
1828         rmb->pinfo = NULL;
1829         rmb->attrs = mb->attrs;
1830         rmb->iattrs = 0;
1831         rmb->call_conv = mb->call_conv;
1832         rmb->code = NULL;
1833         rmb->type = (MonoObject *) mb->owner;
1834         rmb->name = mb->name;
1835         rmb->table_idx = NULL;
1836         rmb->init_locals = mb->init_locals;
1837         rmb->skip_visibility = mb->skip_visibility;
1838         rmb->return_modreq = NULL;
1839         rmb->return_modopt = NULL;
1840         rmb->param_modreq = NULL;
1841         rmb->param_modopt = NULL;
1842         rmb->permissions = NULL;
1843         rmb->mhandle = mb->mhandle;
1844         rmb->nrefs = 0;
1845         rmb->refs = NULL;
1846 }       
1847 #endif
1848
1849 static gboolean
1850 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1851 {
1852         MONO_REQ_GC_UNSAFE_MODE;
1853
1854         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1855         MonoDynamicTable *table;
1856         guint32 *values;
1857         guint32 tok;
1858         MonoReflectionMethod *m;
1859         int i;
1860
1861         mono_error_init (error);
1862
1863         if (!mb->override_methods)
1864                 return TRUE;
1865
1866         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1867                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1868
1869                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1870                 table->rows ++;
1871                 alloc_table (table, table->rows);
1872                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1873                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1874                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1875
1876                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1877                 return_val_if_nok (error, FALSE);
1878
1879                 switch (mono_metadata_token_table (tok)) {
1880                 case MONO_TABLE_MEMBERREF:
1881                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1882                         break;
1883                 case MONO_TABLE_METHOD:
1884                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1885                         break;
1886                 default:
1887                         g_assert_not_reached ();
1888                 }
1889                 values [MONO_METHODIMPL_DECLARATION] = tok;
1890         }
1891
1892         return TRUE;
1893 }
1894
1895 #ifndef DISABLE_REFLECTION_EMIT
1896 static gboolean
1897 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1898 {
1899         MONO_REQ_GC_UNSAFE_MODE;
1900
1901         MonoDynamicTable *table;
1902         guint32 *values;
1903         ReflectionMethodBuilder rmb;
1904         int i;
1905
1906         mono_error_init (error);
1907
1908         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1909             !mono_image_basic_method (&rmb, assembly, error))
1910                 return FALSE;
1911
1912         mb->table_idx = *rmb.table_idx;
1913
1914         if (mb->dll) { /* It's a P/Invoke method */
1915                 guint32 moduleref;
1916                 /* map CharSet values to on-disk values */
1917                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1918                 int extra_flags = mb->extra_flags;
1919                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1920                 table->rows ++;
1921                 alloc_table (table, table->rows);
1922                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1923                 
1924                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1925                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1926                 if (mb->dllentry)
1927                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1928                 else
1929                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1930                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1931                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1932                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1933                         table->rows ++;
1934                         alloc_table (table, table->rows);
1935                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1936                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1937                 }
1938         }
1939
1940         if (mb->generic_params) {
1941                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1942                 table->rows += mono_array_length (mb->generic_params);
1943                 alloc_table (table, table->rows);
1944                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1945                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1946
1947                         mono_image_get_generic_param_info (
1948                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1949                 }
1950         }
1951
1952         return TRUE;
1953 }
1954
1955 static gboolean
1956 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1957 {
1958         MONO_REQ_GC_UNSAFE_MODE;
1959
1960         ReflectionMethodBuilder rmb;
1961
1962         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1963                 return FALSE;
1964
1965         if (!mono_image_basic_method (&rmb, assembly, error))
1966                 return FALSE;
1967
1968         mb->table_idx = *rmb.table_idx;
1969
1970         return TRUE;
1971 }
1972 #endif
1973
1974 static char*
1975 type_get_fully_qualified_name (MonoType *type)
1976 {
1977         MONO_REQ_GC_NEUTRAL_MODE;
1978
1979         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1980 }
1981
1982 static char*
1983 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1984 {
1985         MONO_REQ_GC_UNSAFE_MODE;
1986
1987         MonoClass *klass;
1988         MonoAssembly *ta;
1989
1990         klass = mono_class_from_mono_type (type);
1991         if (!klass) 
1992                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1993         ta = klass->image->assembly;
1994         if (assembly_is_dynamic (ta) || (ta == ass)) {
1995                 if (klass->generic_class || klass->generic_container)
1996                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1997                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1998                 else
1999                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
2000         }
2001
2002         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
2003 }
2004
2005 #ifndef DISABLE_REFLECTION_EMIT
2006 /*field_image is the image to which the eventual custom mods have been encoded against*/
2007 static guint32
2008 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
2009 {
2010         MONO_REQ_GC_NEUTRAL_MODE;
2011
2012         SigBuffer buf;
2013         guint32 idx, i, token;
2014
2015         if (!assembly->save)
2016                 return 0;
2017
2018         sigbuffer_init (&buf, 32);
2019         
2020         sigbuffer_add_value (&buf, 0x06);
2021         /* encode custom attributes before the type */
2022         if (type->num_mods) {
2023                 for (i = 0; i < type->num_mods; ++i) {
2024                         if (field_image) {
2025                                 MonoError error;
2026                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
2027                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2028
2029                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
2030                         } else {
2031                                 token = type->modifiers [i].token;
2032                         }
2033
2034                         if (type->modifiers [i].required)
2035                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
2036                         else
2037                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
2038
2039                         sigbuffer_add_value (&buf, token);
2040                 }
2041         }
2042         encode_type (assembly, type, &buf);
2043         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2044         sigbuffer_free (&buf);
2045         return idx;
2046 }
2047 #endif
2048
2049 static guint32
2050 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
2051 {
2052         MONO_REQ_GC_UNSAFE_MODE;
2053
2054         mono_error_init (error);
2055
2056         SigBuffer buf;
2057         guint32 idx;
2058         guint32 typespec = 0;
2059         MonoType *type;
2060         MonoClass *klass;
2061
2062         init_type_builder_generics (fb->type);
2063
2064         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
2065         return_val_if_nok (error, 0);
2066         klass = mono_class_from_mono_type (type);
2067
2068         sigbuffer_init (&buf, 32);
2069         
2070         sigbuffer_add_value (&buf, 0x06);
2071         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
2072         if (!is_ok (error))
2073                 goto fail;
2074         /* encode custom attributes before the type */
2075
2076         if (klass->generic_container)
2077                 typespec = create_typespec (assembly, type);
2078
2079         if (typespec) {
2080                 MonoGenericClass *gclass;
2081                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2082                 encode_generic_class (assembly, gclass, &buf);
2083         } else {
2084                 encode_type (assembly, type, &buf);
2085         }
2086         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2087         sigbuffer_free (&buf);
2088         return idx;
2089 fail:
2090         sigbuffer_free (&buf);
2091         return 0;
2092 }
2093
2094 static guint32
2095 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2096 {
2097         MONO_REQ_GC_UNSAFE_MODE;
2098
2099         char blob_size [64];
2100         char *b = blob_size;
2101         char *box_val;
2102         char* buf;
2103         guint32 idx = 0, len = 0, dummy = 0;
2104
2105         buf = (char *)g_malloc (64);
2106         if (!val) {
2107                 *ret_type = MONO_TYPE_CLASS;
2108                 len = 4;
2109                 box_val = (char*)&dummy;
2110         } else {
2111                 box_val = ((char*)val) + sizeof (MonoObject);
2112                 *ret_type = val->vtable->klass->byval_arg.type;
2113         }
2114 handle_enum:
2115         switch (*ret_type) {
2116         case MONO_TYPE_BOOLEAN:
2117         case MONO_TYPE_U1:
2118         case MONO_TYPE_I1:
2119                 len = 1;
2120                 break;
2121         case MONO_TYPE_CHAR:
2122         case MONO_TYPE_U2:
2123         case MONO_TYPE_I2:
2124                 len = 2;
2125                 break;
2126         case MONO_TYPE_U4:
2127         case MONO_TYPE_I4:
2128         case MONO_TYPE_R4:
2129                 len = 4;
2130                 break;
2131         case MONO_TYPE_U8:
2132         case MONO_TYPE_I8:
2133                 len = 8;
2134                 break;
2135         case MONO_TYPE_R8:
2136                 len = 8;
2137                 break;
2138         case MONO_TYPE_VALUETYPE: {
2139                 MonoClass *klass = val->vtable->klass;
2140                 
2141                 if (klass->enumtype) {
2142                         *ret_type = mono_class_enum_basetype (klass)->type;
2143                         goto handle_enum;
2144                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2145                         len = 8;
2146                 } else 
2147                         g_error ("we can't encode valuetypes, we should have never reached this line");
2148                 break;
2149         }
2150         case MONO_TYPE_CLASS:
2151                 break;
2152         case MONO_TYPE_STRING: {
2153                 MonoString *str = (MonoString*)val;
2154                 /* there is no signature */
2155                 len = str->length * 2;
2156                 mono_metadata_encode_value (len, b, &b);
2157 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2158                 {
2159                         char *swapped = g_malloc (2 * mono_string_length (str));
2160                         const char *p = (const char*)mono_string_chars (str);
2161
2162                         swap_with_size (swapped, p, 2, mono_string_length (str));
2163                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2164                         g_free (swapped);
2165                 }
2166 #else
2167                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2168 #endif
2169
2170                 g_free (buf);
2171                 return idx;
2172         }
2173         case MONO_TYPE_GENERICINST:
2174                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2175                 goto handle_enum;
2176         default:
2177                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2178         }
2179
2180         /* there is no signature */
2181         mono_metadata_encode_value (len, b, &b);
2182 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2183         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2184         swap_with_size (blob_size, box_val, len, 1);
2185         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2186 #else
2187         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2188 #endif
2189
2190         g_free (buf);
2191         return idx;
2192 }
2193
2194 static guint32
2195 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
2196 {
2197         MONO_REQ_GC_UNSAFE_MODE;
2198
2199         mono_error_init (error);
2200
2201         char *str;
2202         SigBuffer buf;
2203         guint32 idx, len;
2204
2205         sigbuffer_init (&buf, 32);
2206
2207         sigbuffer_add_value (&buf, minfo->type);
2208
2209         switch (minfo->type) {
2210         case MONO_NATIVE_BYVALTSTR:
2211         case MONO_NATIVE_BYVALARRAY:
2212                 sigbuffer_add_value (&buf, minfo->count);
2213                 break;
2214         case MONO_NATIVE_LPARRAY:
2215                 if (minfo->eltype || minfo->has_size) {
2216                         sigbuffer_add_value (&buf, minfo->eltype);
2217                         if (minfo->has_size) {
2218                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2219                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2220
2221                                 /* LAMESPEC: ElemMult is undocumented */
2222                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2223                         }
2224                 }
2225                 break;
2226         case MONO_NATIVE_SAFEARRAY:
2227                 if (minfo->eltype)
2228                         sigbuffer_add_value (&buf, minfo->eltype);
2229                 break;
2230         case MONO_NATIVE_CUSTOM:
2231                 if (minfo->guid) {
2232                         str = mono_string_to_utf8 (minfo->guid);
2233                         len = strlen (str);
2234                         sigbuffer_add_value (&buf, len);
2235                         sigbuffer_add_mem (&buf, str, len);
2236                         g_free (str);
2237                 } else {
2238                         sigbuffer_add_value (&buf, 0);
2239                 }
2240                 /* native type name */
2241                 sigbuffer_add_value (&buf, 0);
2242                 /* custom marshaler type name */
2243                 if (minfo->marshaltype || minfo->marshaltyperef) {
2244                         if (minfo->marshaltyperef) {
2245                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2246                                 if (!is_ok (error)) {
2247                                         sigbuffer_free (&buf);
2248                                         return 0;
2249                                 }
2250                                 str = type_get_fully_qualified_name (marshaltype);
2251                         } else
2252                                 str = mono_string_to_utf8 (minfo->marshaltype);
2253                         len = strlen (str);
2254                         sigbuffer_add_value (&buf, len);
2255                         sigbuffer_add_mem (&buf, str, len);
2256                         g_free (str);
2257                 } else {
2258                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2259                         sigbuffer_add_value (&buf, 0);
2260                 }
2261                 if (minfo->mcookie) {
2262                         str = mono_string_to_utf8 (minfo->mcookie);
2263                         len = strlen (str);
2264                         sigbuffer_add_value (&buf, len);
2265                         sigbuffer_add_mem (&buf, str, len);
2266                         g_free (str);
2267                 } else {
2268                         sigbuffer_add_value (&buf, 0);
2269                 }
2270                 break;
2271         default:
2272                 break;
2273         }
2274         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2275         sigbuffer_free (&buf);
2276         return idx;
2277 }
2278
2279 static void
2280 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly, MonoError *error)
2281 {
2282         MONO_REQ_GC_UNSAFE_MODE;
2283
2284         mono_error_init (error);
2285
2286         MonoDynamicTable *table;
2287         guint32 *values;
2288
2289         /* maybe this fixup should be done in the C# code */
2290         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2291                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2292         table = &assembly->tables [MONO_TABLE_FIELD];
2293         fb->table_idx = table->next_idx ++;
2294         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2295         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2296         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2297         values [MONO_FIELD_FLAGS] = fb->attrs;
2298         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb, error);
2299         return_if_nok (error);
2300
2301
2302         if (fb->offset != -1) {
2303                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2304                 table->rows ++;
2305                 alloc_table (table, table->rows);
2306                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2307                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2308                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2309         }
2310         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2311                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2312                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2313                 table->rows ++;
2314                 alloc_table (table, table->rows);
2315                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2316                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2317                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2318                 values [MONO_CONSTANT_TYPE] = field_type;
2319                 values [MONO_CONSTANT_PADDING] = 0;
2320         }
2321         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2322                 guint32 rva_idx;
2323                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2324                 table->rows ++;
2325                 alloc_table (table, table->rows);
2326                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2327                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2328                 /*
2329                  * We store it in the code section because it's simpler for now.
2330                  */
2331                 if (fb->rva_data) {
2332                         if (mono_array_length (fb->rva_data) >= 10)
2333                                 stream_data_align (&assembly->code);
2334                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2335                 } else
2336                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2337                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2338         }
2339         if (fb->marshal_info) {
2340                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2341                 table->rows ++;
2342                 alloc_table (table, table->rows);
2343                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2344                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2345                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info, error);
2346                 return_if_nok (error);
2347         }
2348 }
2349
2350 static guint32
2351 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
2352 {
2353         MONO_REQ_GC_UNSAFE_MODE;
2354
2355         mono_error_init (error);
2356
2357         SigBuffer buf;
2358         guint32 nparams = 0;
2359         MonoReflectionMethodBuilder *mb = fb->get_method;
2360         MonoReflectionMethodBuilder *smb = fb->set_method;
2361         guint32 idx, i;
2362
2363         if (mb && mb->parameters)
2364                 nparams = mono_array_length (mb->parameters);
2365         if (!mb && smb && smb->parameters)
2366                 nparams = mono_array_length (smb->parameters) - 1;
2367         sigbuffer_init (&buf, 32);
2368         if (fb->call_conv & 0x20)
2369                 sigbuffer_add_byte (&buf, 0x28);
2370         else
2371                 sigbuffer_add_byte (&buf, 0x08);
2372         sigbuffer_add_value (&buf, nparams);
2373         if (mb) {
2374                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
2375                 if (!is_ok (error))
2376                         goto fail;
2377                 for (i = 0; i < nparams; ++i) {
2378                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2379                         encode_reflection_type (assembly, pt, &buf, error);
2380                         if (!is_ok (error))
2381                                 goto fail;
2382                 }
2383         } else if (smb && smb->parameters) {
2384                 /* the property type is the last param */
2385                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
2386                 if (!is_ok (error))
2387                         goto fail;
2388
2389                 for (i = 0; i < nparams; ++i) {
2390                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2391                         encode_reflection_type (assembly, pt, &buf, error);
2392                         if (!is_ok (error))
2393                                 goto fail;
2394                 }
2395         } else {
2396                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
2397                 if (!is_ok (error))
2398                         goto fail;
2399         }
2400
2401         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2402         sigbuffer_free (&buf);
2403         return idx;
2404 fail:
2405         sigbuffer_free (&buf);
2406         return 0;
2407 }
2408
2409 static void
2410 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly, MonoError *error)
2411 {
2412         MONO_REQ_GC_UNSAFE_MODE;
2413
2414         mono_error_init (error);
2415
2416         MonoDynamicTable *table;
2417         guint32 *values;
2418         guint num_methods = 0;
2419         guint32 semaidx;
2420
2421         /* 
2422          * we need to set things in the following tables:
2423          * PROPERTYMAP (info already filled in _get_type_info ())
2424          * PROPERTY    (rows already preallocated in _get_type_info ())
2425          * METHOD      (method info already done with the generic method code)
2426          * METHODSEMANTICS
2427          * CONSTANT
2428          */
2429         table = &assembly->tables [MONO_TABLE_PROPERTY];
2430         pb->table_idx = table->next_idx ++;
2431         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2432         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2433         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2434         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb, error);
2435         return_if_nok (error);
2436
2437
2438         /* FIXME: we still don't handle 'other' methods */
2439         if (pb->get_method) num_methods ++;
2440         if (pb->set_method) num_methods ++;
2441
2442         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2443         table->rows += num_methods;
2444         alloc_table (table, table->rows);
2445
2446         if (pb->get_method) {
2447                 semaidx = table->next_idx ++;
2448                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2449                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2450                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2451                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2452         }
2453         if (pb->set_method) {
2454                 semaidx = table->next_idx ++;
2455                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2456                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2457                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2458                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2459         }
2460         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2461                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2462                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2463                 table->rows ++;
2464                 alloc_table (table, table->rows);
2465                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2466                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2467                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2468                 values [MONO_CONSTANT_TYPE] = field_type;
2469                 values [MONO_CONSTANT_PADDING] = 0;
2470         }
2471 }
2472
2473 static void
2474 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly, MonoError *error)
2475 {
2476         MONO_REQ_GC_UNSAFE_MODE;
2477
2478         MonoDynamicTable *table;
2479         guint32 *values;
2480         guint num_methods = 0;
2481         guint32 semaidx;
2482
2483         /* 
2484          * we need to set things in the following tables:
2485          * EVENTMAP (info already filled in _get_type_info ())
2486          * EVENT    (rows already preallocated in _get_type_info ())
2487          * METHOD      (method info already done with the generic method code)
2488          * METHODSEMANTICS
2489          */
2490         table = &assembly->tables [MONO_TABLE_EVENT];
2491         eb->table_idx = table->next_idx ++;
2492         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2493         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2494         values [MONO_EVENT_FLAGS] = eb->attrs;
2495         MonoType *ebtype = mono_reflection_type_get_handle (eb->type, error);
2496         return_if_nok (error);
2497         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, ebtype);
2498
2499         /*
2500          * FIXME: we still don't handle 'other' methods 
2501          */
2502         if (eb->add_method) num_methods ++;
2503         if (eb->remove_method) num_methods ++;
2504         if (eb->raise_method) num_methods ++;
2505
2506         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2507         table->rows += num_methods;
2508         alloc_table (table, table->rows);
2509
2510         if (eb->add_method) {
2511                 semaidx = table->next_idx ++;
2512                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2513                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2514                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2515                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2516         }
2517         if (eb->remove_method) {
2518                 semaidx = table->next_idx ++;
2519                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2520                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2521                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2522                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2523         }
2524         if (eb->raise_method) {
2525                 semaidx = table->next_idx ++;
2526                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2527                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2528                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2529                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2530         }
2531 }
2532
2533 static void
2534 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly, MonoError *error)
2535 {
2536         MONO_REQ_GC_UNSAFE_MODE;
2537
2538         mono_error_init (error);
2539
2540         MonoDynamicTable *table;
2541         guint32 num_constraints, i;
2542         guint32 *values;
2543         guint32 table_idx;
2544
2545         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2546         num_constraints = gparam->iface_constraints ?
2547                 mono_array_length (gparam->iface_constraints) : 0;
2548         table->rows += num_constraints;
2549         if (gparam->base_type)
2550                 table->rows++;
2551         alloc_table (table, table->rows);
2552
2553         if (gparam->base_type) {
2554                 table_idx = table->next_idx ++;
2555                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2556
2557                 MonoType *gpbasetype = mono_reflection_type_get_handle (gparam->base_type, error);
2558                 return_if_nok (error);
2559                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2560                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, gpbasetype);
2561         }
2562
2563         for (i = 0; i < num_constraints; i++) {
2564                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2565                         gparam->iface_constraints, gpointer, i);
2566
2567                 table_idx = table->next_idx ++;
2568                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2569
2570                 MonoType *constraint_type = mono_reflection_type_get_handle (constraint, error);
2571                 return_if_nok (error);
2572
2573                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2574                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint_type);
2575         }
2576 }
2577
2578 static void
2579 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2580 {
2581         MONO_REQ_GC_UNSAFE_MODE;
2582
2583         GenericParamTableEntry *entry;
2584
2585         /*
2586          * The GenericParam table must be sorted according to the `owner' field.
2587          * We need to do this sorting prior to writing the GenericParamConstraint
2588          * table, since we have to use the final GenericParam table indices there
2589          * and they must also be sorted.
2590          */
2591
2592         entry = g_new0 (GenericParamTableEntry, 1);
2593         entry->owner = owner;
2594         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2595         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2596         entry->gparam = gparam;
2597         
2598         g_ptr_array_add (assembly->gen_params, entry);
2599 }
2600
2601 static gboolean
2602 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2603 {
2604         MONO_REQ_GC_UNSAFE_MODE;
2605
2606         MonoDynamicTable *table;
2607         MonoGenericParam *param;
2608         guint32 *values;
2609         guint32 table_idx;
2610
2611         mono_error_init (error);
2612
2613         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2614         table_idx = table->next_idx ++;
2615         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2616
2617         MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam, error);
2618         return_val_if_nok (error, FALSE);
2619
2620         param = gparam_type->data.generic_param;
2621
2622         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2623         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2624         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2625         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2626
2627         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2628                 return FALSE;
2629
2630         encode_constraints (entry->gparam, table_idx, assembly, error);
2631         return_val_if_nok (error, FALSE);
2632
2633         return TRUE;
2634 }
2635
2636 static guint32
2637 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2638 {
2639         MONO_REQ_GC_UNSAFE_MODE;
2640
2641         MonoDynamicTable *table;
2642         guint32 token;
2643         guint32 *values;
2644         guint32 cols [MONO_ASSEMBLY_SIZE];
2645         const char *pubkey;
2646         guint32 publen;
2647
2648         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2649                 return token;
2650
2651         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2652                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2653                 token = table->next_idx ++;
2654                 table->rows ++;
2655                 alloc_table (table, table->rows);
2656                 values = table->values + token * MONO_MODULEREF_SIZE;
2657                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2658
2659                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2660                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2661                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2662
2663                 return token;
2664         }
2665         
2666         if (assembly_is_dynamic (image->assembly))
2667                 /* FIXME: */
2668                 memset (cols, 0, sizeof (cols));
2669         else {
2670                 /* image->assembly->image is the manifest module */
2671                 image = image->assembly->image;
2672                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2673         }
2674
2675         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2676         token = table->next_idx ++;
2677         table->rows ++;
2678         alloc_table (table, table->rows);
2679         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2680         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2681         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2682         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2683         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2684         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2685         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2686         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2687         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2688
2689         if (strcmp ("", image->assembly->aname.culture)) {
2690                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2691                                 image->assembly->aname.culture);
2692         }
2693
2694         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2695                 guchar pubtoken [9];
2696                 pubtoken [0] = 8;
2697                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2698                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2699         } else {
2700                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2701         }
2702         token <<= MONO_RESOLUTION_SCOPE_BITS;
2703         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2704         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2705         return token;
2706 }
2707
2708 static guint32
2709 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2710 {
2711         MONO_REQ_GC_NEUTRAL_MODE;
2712
2713         MonoDynamicTable *table;
2714         guint32 *values;
2715         guint32 token;
2716         SigBuffer buf;
2717
2718         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2719                 return token;
2720
2721         sigbuffer_init (&buf, 32);
2722         switch (type->type) {
2723         case MONO_TYPE_FNPTR:
2724         case MONO_TYPE_PTR:
2725         case MONO_TYPE_SZARRAY:
2726         case MONO_TYPE_ARRAY:
2727         case MONO_TYPE_VAR:
2728         case MONO_TYPE_MVAR:
2729         case MONO_TYPE_GENERICINST:
2730                 encode_type (assembly, type, &buf);
2731                 break;
2732         case MONO_TYPE_CLASS:
2733         case MONO_TYPE_VALUETYPE: {
2734                 MonoClass *k = mono_class_from_mono_type (type);
2735                 if (!k || !k->generic_container) {
2736                         sigbuffer_free (&buf);
2737                         return 0;
2738                 }
2739                 encode_type (assembly, type, &buf);
2740                 break;
2741         }
2742         default:
2743                 sigbuffer_free (&buf);
2744                 return 0;
2745         }
2746
2747         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2748         if (assembly->save) {
2749                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2750                 alloc_table (table, table->rows + 1);
2751                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2752                 values [MONO_TYPESPEC_SIGNATURE] = token;
2753         }
2754         sigbuffer_free (&buf);
2755
2756         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2757         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2758         table->next_idx ++;
2759         return token;
2760 }
2761
2762 static guint32
2763 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2764 {
2765         MONO_REQ_GC_UNSAFE_MODE;
2766
2767         MonoDynamicTable *table;
2768         guint32 *values;
2769         guint32 token, scope, enclosing;
2770         MonoClass *klass;
2771
2772         /* if the type requires a typespec, we must try that first*/
2773         if (try_typespec && (token = create_typespec (assembly, type)))
2774                 return token;
2775         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2776         if (token)
2777                 return token;
2778         klass = mono_class_from_mono_type (type);
2779         if (!klass)
2780                 klass = mono_class_from_mono_type (type);
2781
2782         /*
2783          * If it's in the same module and not a generic type parameter:
2784          */
2785         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2786                         (type->type != MONO_TYPE_MVAR)) {
2787                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2788                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2789                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2790                 return token;
2791         }
2792
2793         if (klass->nested_in) {
2794                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2795                 /* get the typeref idx of the enclosing type */
2796                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2797                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2798         } else {
2799                 scope = resolution_scope_from_image (assembly, klass->image);
2800         }
2801         table = &assembly->tables [MONO_TABLE_TYPEREF];
2802         if (assembly->save) {
2803                 alloc_table (table, table->rows + 1);
2804                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2805                 values [MONO_TYPEREF_SCOPE] = scope;
2806                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2807                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2808         }
2809         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2810         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2811         table->next_idx ++;
2812         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2813         return token;
2814 }
2815
2816 /*
2817  * Despite the name, we handle also TypeSpec (with the above helper).
2818  */
2819 static guint32
2820 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2821 {
2822         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2823 }
2824
2825 #ifndef DISABLE_REFLECTION_EMIT
2826 static guint32
2827 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2828 {
2829         MONO_REQ_GC_NEUTRAL_MODE;
2830
2831         MonoDynamicTable *table;
2832         guint32 *values;
2833         guint32 token, pclass;
2834
2835         switch (parent & MONO_TYPEDEFORREF_MASK) {
2836         case MONO_TYPEDEFORREF_TYPEREF:
2837                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2838                 break;
2839         case MONO_TYPEDEFORREF_TYPESPEC:
2840                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2841                 break;
2842         case MONO_TYPEDEFORREF_TYPEDEF:
2843                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2844                 break;
2845         default:
2846                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2847                 return 0;
2848         }
2849         /* extract the index */
2850         parent >>= MONO_TYPEDEFORREF_BITS;
2851
2852         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2853
2854         if (assembly->save) {
2855                 alloc_table (table, table->rows + 1);
2856                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2857                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2858                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2859                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2860         }
2861
2862         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2863         table->next_idx ++;
2864
2865         return token;
2866 }
2867
2868 /*
2869  * Insert a memberef row into the metadata: the token that point to the memberref
2870  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2871  * mono_image_get_fieldref_token()).
2872  * The sig param is an index to an already built signature.
2873  */
2874 static guint32
2875 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2876 {
2877         MONO_REQ_GC_NEUTRAL_MODE;
2878
2879         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2880         return mono_image_add_memberef_row (assembly, parent, name, sig);
2881 }
2882
2883
2884 static guint32
2885 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2886 {
2887         MONO_REQ_GC_NEUTRAL_MODE;
2888
2889         guint32 token;
2890         MonoMethodSignature *sig;
2891         
2892         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2893
2894         if (create_typespec) {
2895                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2896                 if (token)
2897                         return token;
2898         } 
2899
2900         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2901         if (token && !create_typespec)
2902                 return token;
2903
2904         g_assert (!method->is_inflated);
2905         if (!token) {
2906                 /*
2907                  * A methodref signature can't contain an unmanaged calling convention.
2908                  */
2909                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2910                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2911                         sig->call_convention = MONO_CALL_DEFAULT;
2912                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2913                         method->name,  method_encode_signature (assembly, sig));
2914                 g_free (sig);
2915                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2916         }
2917
2918         if (create_typespec) {
2919                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2920                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2921                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2922
2923                 if (assembly->save) {
2924                         guint32 *values;
2925
2926                         alloc_table (table, table->rows + 1);
2927                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2928                         values [MONO_METHODSPEC_METHOD] = token;
2929                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2930                 }
2931
2932                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2933                 table->next_idx ++;
2934                 /*methodspec and memberef tokens are diferent, */
2935                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2936                 return token;
2937         }
2938         return token;
2939 }
2940
2941 static guint32
2942 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2943 {
2944         guint32 token, parent, sig;
2945         ReflectionMethodBuilder rmb;
2946         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2947         
2948         mono_error_init (error);
2949         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2950         if (token)
2951                 return token;
2952
2953         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2954                 return 0;
2955
2956         /*
2957          * A methodref signature can't contain an unmanaged calling convention.
2958          * Since some flags are encoded as part of call_conv, we need to check against it.
2959         */
2960         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2961                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2962
2963         sig = method_builder_encode_signature (assembly, &rmb, error);
2964         return_val_if_nok (error, 0);
2965
2966         if (tb->generic_params) {
2967                 parent = create_generic_typespec (assembly, tb, error);
2968                 return_val_if_nok (error, 0);
2969         } else {
2970                 MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type, error);
2971                 return_val_if_nok (error, 0);
2972
2973                 parent = mono_image_typedef_or_ref (assembly, t);
2974         }
2975
2976         char *name = mono_string_to_utf8 (method->name);
2977
2978         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2979         g_free (name);
2980
2981         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2982
2983         return token;
2984 }
2985
2986 static guint32
2987 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2988                                      const gchar *name, guint32 sig)
2989 {
2990         MonoDynamicTable *table;
2991         guint32 token;
2992         guint32 *values;
2993         
2994         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2995
2996         if (assembly->save) {
2997                 alloc_table (table, table->rows + 1);
2998                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2999                 values [MONO_MEMBERREF_CLASS] = original;
3000                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3001                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3002         }
3003
3004         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3005         table->next_idx ++;
3006
3007         return token;
3008 }
3009
3010 static guint32
3011 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
3012 {
3013         SigBuffer buf;
3014         int i;
3015         guint32 nparams = mono_array_length (mb->generic_params);
3016         guint32 idx;
3017
3018         if (!assembly->save)
3019                 return 0;
3020
3021         sigbuffer_init (&buf, 32);
3022
3023         sigbuffer_add_value (&buf, 0xa);
3024         sigbuffer_add_value (&buf, nparams);
3025
3026         for (i = 0; i < nparams; i++) {
3027                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
3028                 sigbuffer_add_value (&buf, i);
3029         }
3030
3031         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3032         sigbuffer_free (&buf);
3033         return idx;
3034 }
3035
3036 static guint32
3037 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
3038 {
3039         MonoDynamicTable *table;
3040         guint32 *values;
3041         guint32 token, mtoken = 0;
3042
3043         mono_error_init (error);
3044         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
3045         if (token)
3046                 return token;
3047
3048         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3049
3050         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3051         if (!mono_error_ok (error))
3052                 return 0;
3053
3054         switch (mono_metadata_token_table (mtoken)) {
3055         case MONO_TABLE_MEMBERREF:
3056                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3057                 break;
3058         case MONO_TABLE_METHOD:
3059                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3060                 break;
3061         default:
3062                 g_assert_not_reached ();
3063         }
3064
3065         if (assembly->save) {
3066                 alloc_table (table, table->rows + 1);
3067                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3068                 values [MONO_METHODSPEC_METHOD] = mtoken;
3069                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
3070         }
3071
3072         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3073         table->next_idx ++;
3074
3075         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
3076         return token;
3077 }
3078
3079 static guint32
3080 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
3081 {
3082         guint32 token;
3083
3084         mono_error_init (error);
3085
3086         if (mb->generic_params && create_methodspec) 
3087                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
3088
3089         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3090         if (token)
3091                 return token;
3092
3093         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
3094         if (!mono_error_ok (error))
3095                 return 0;
3096         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3097         return token;
3098 }
3099
3100 static guint32
3101 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
3102 {
3103         guint32 token, parent, sig;
3104         ReflectionMethodBuilder rmb;
3105         char *name;
3106         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
3107         
3108         mono_error_init (error);
3109         
3110         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
3111         if (token)
3112                 return token;
3113
3114         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3115                 return 0;
3116
3117         if (tb->generic_params) {
3118                 parent = create_generic_typespec (assembly, tb, error);
3119                 return_val_if_nok (error, 0);
3120         } else {
3121                 MonoType * type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3122                 return_val_if_nok (error, 0);
3123                 parent = mono_image_typedef_or_ref (assembly, type);
3124         }
3125         
3126         name = mono_string_to_utf8 (rmb.name);
3127         sig = method_builder_encode_signature (assembly, &rmb, error);
3128         return_val_if_nok (error, 0);
3129
3130         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3131
3132         g_free (name);
3133         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3134         return token;
3135 }
3136 #endif
3137
3138 static gboolean
3139 is_field_on_inst (MonoClassField *field)
3140 {
3141         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3142 }
3143
3144 /*
3145  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3146  */
3147 static MonoType*
3148 get_field_on_inst_generic_type (MonoClassField *field)
3149 {
3150         MonoClass *klass, *gtd;
3151         MonoDynamicGenericClass *dgclass;
3152         int field_index;
3153
3154         g_assert (is_field_on_inst (field));
3155
3156         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3157
3158         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3159                 field_index = field - dgclass->fields;
3160                 return dgclass->field_generic_types [field_index];              
3161         }
3162
3163         klass = field->parent;
3164         gtd = klass->generic_class->container_class;
3165
3166         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3167                 field_index = field - klass->fields;
3168                 return gtd->fields [field_index].type;
3169         }
3170
3171         g_assert_not_reached ();
3172         return 0;
3173 }
3174
3175 #ifndef DISABLE_REFLECTION_EMIT
3176 static guint32
3177 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3178 {
3179         MonoType *type;
3180         guint32 token;
3181
3182         g_assert (field);
3183         g_assert (field->parent);
3184
3185         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3186         if (token)
3187                 return token;
3188
3189         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3190                 int index = field - field->parent->fields;
3191                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3192         } else {
3193                 if (is_field_on_inst (field))
3194                         type = get_field_on_inst_generic_type (field);
3195                 else
3196                         type = mono_field_get_type (field);
3197         }
3198         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3199                                                                                         mono_field_get_name (field),
3200                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3201         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3202         return token;
3203 }
3204
3205 static guint32
3206 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f, MonoError *error)
3207 {
3208         guint32 token;
3209         MonoClass *klass;
3210         MonoGenericClass *gclass;
3211         MonoType *type;
3212         char *name;
3213
3214         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3215         if (token)
3216                 return token;
3217         if (is_sre_field_builder (mono_object_class (f->fb))) {
3218                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3219                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3220                 return_val_if_nok (error, 0);
3221                 klass = mono_class_from_mono_type (type);
3222                 gclass = type->data.generic_class;
3223                 g_assert (gclass->is_dynamic);
3224
3225                 guint32 sig_token = field_encode_signature (assembly, fb, error);
3226                 return_val_if_nok (error, 0);
3227                 name = mono_string_to_utf8 (fb->name);
3228                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig_token);
3229                 g_free (name);          
3230         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3231                 guint32 sig;
3232                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3233
3234                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, error);
3235                 return_val_if_nok (error, 0);
3236                 klass = mono_class_from_mono_type (type);
3237
3238                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3239                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3240         } else {
3241                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3242                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3243         }
3244
3245         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3246         return token;
3247 }
3248
3249 static guint32
3250 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3251 {
3252         guint32 sig, token;
3253         MonoClass *klass;
3254         MonoGenericClass *gclass;
3255         MonoType *type;
3256
3257         mono_error_init (error);
3258
3259         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3260
3261         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3262         if (token)
3263                 return token;
3264
3265         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3266                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3267                 ReflectionMethodBuilder rmb;
3268                 char *name;
3269
3270                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3271                 return_val_if_nok (error, 0);
3272                 klass = mono_class_from_mono_type (type);
3273
3274                 gclass = type->data.generic_class;
3275                 g_assert (gclass->is_dynamic);
3276
3277                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3278                         return 0;
3279
3280                 sig = method_builder_encode_signature (assembly, &rmb, error);
3281                 return_val_if_nok (error, 0);
3282
3283                 name = mono_string_to_utf8 (rmb.name);
3284
3285                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3286                 g_free (name);
3287         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3288                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3289
3290                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, error);
3291                 return_val_if_nok (error, 0);
3292                 klass = mono_class_from_mono_type (type);
3293
3294                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3295                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3296         } else {
3297                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3298                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3299         }
3300
3301
3302         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3303         return token;
3304 }
3305
3306 static MonoMethod*
3307 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3308 {
3309         MonoClass *klass;
3310         MonoGenericContext tmp_context;
3311         MonoType **type_argv;
3312         MonoGenericInst *ginst;
3313         MonoMethod *method, *inflated;
3314         int count, i;
3315
3316         mono_error_init (error);
3317
3318         init_type_builder_generics ((MonoObject*)m->inst);
3319
3320         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3321         return_val_if_nok (error, NULL);
3322
3323         klass = method->klass;
3324
3325         if (m->method_args == NULL)
3326                 return method;
3327
3328         if (method->is_inflated)
3329                 method = ((MonoMethodInflated *) method)->declaring;
3330
3331         count = mono_array_length (m->method_args);
3332
3333         type_argv = g_new0 (MonoType *, count);
3334         for (i = 0; i < count; i++) {
3335                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3336                 type_argv [i] = mono_reflection_type_get_handle (garg, error);
3337                 return_val_if_nok (error, NULL);
3338         }
3339         ginst = mono_metadata_get_generic_inst (count, type_argv);
3340         g_free (type_argv);
3341
3342         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3343         tmp_context.method_inst = ginst;
3344
3345         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3346         mono_error_assert_ok (error);
3347         return inflated;
3348 }
3349
3350 static guint32
3351 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3352 {
3353         guint32 sig, token = 0;
3354         MonoType *type;
3355         MonoClass *klass;
3356
3357         mono_error_init (error);
3358
3359         if (m->method_args) {
3360                 MonoMethod *inflated;
3361
3362                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3363                 return_val_if_nok (error, 0);
3364
3365                 if (create_methodspec)
3366                         token = mono_image_get_methodspec_token (assembly, inflated);
3367                 else
3368                         token = mono_image_get_inflated_method_token (assembly, inflated);
3369                 return token;
3370         }
3371
3372         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3373         if (token)
3374                 return token;
3375
3376         if (is_sre_method_builder (mono_object_class (m->mb))) {
3377                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3378                 MonoGenericClass *gclass;
3379                 ReflectionMethodBuilder rmb;
3380                 char *name;
3381
3382                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3383                 return_val_if_nok (error, 0);
3384                 klass = mono_class_from_mono_type (type);
3385                 gclass = type->data.generic_class;
3386                 g_assert (gclass->is_dynamic);
3387
3388                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3389                         return 0;
3390
3391                 sig = method_builder_encode_signature (assembly, &rmb, error);
3392                 return_val_if_nok (error, 0);
3393
3394                 name = mono_string_to_utf8 (rmb.name);
3395
3396                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3397                 g_free (name);          
3398         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3399                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3400
3401                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, error);
3402                 return_val_if_nok (error, 0);
3403                 klass = mono_class_from_mono_type (type);
3404
3405                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3406                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3407         } else {
3408                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3409                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3410         }
3411
3412         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3413         return token;
3414 }
3415
3416 static guint32
3417 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3418 {
3419         SigBuffer buf;
3420         int i;
3421         guint32 nparams = context->method_inst->type_argc;
3422         guint32 idx;
3423
3424         if (!assembly->save)
3425                 return 0;
3426
3427         sigbuffer_init (&buf, 32);
3428         /*
3429          * FIXME: vararg, explicit_this, differenc call_conv values...
3430          */
3431         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3432         sigbuffer_add_value (&buf, nparams);
3433
3434         for (i = 0; i < nparams; i++)
3435                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3436
3437         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3438         sigbuffer_free (&buf);
3439         return idx;
3440 }
3441
3442 static guint32
3443 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3444 {
3445         MonoDynamicTable *table;
3446         guint32 *values;
3447         guint32 token, mtoken = 0, sig;
3448         MonoMethodInflated *imethod;
3449         MonoMethod *declaring;
3450
3451         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3452
3453         g_assert (method->is_inflated);
3454         imethod = (MonoMethodInflated *) method;
3455         declaring = imethod->declaring;
3456
3457         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3458         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3459
3460         if (!mono_method_signature (declaring)->generic_param_count)
3461                 return mtoken;
3462
3463         switch (mono_metadata_token_table (mtoken)) {
3464         case MONO_TABLE_MEMBERREF:
3465                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3466                 break;
3467         case MONO_TABLE_METHOD:
3468                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3469                 break;
3470         default:
3471                 g_assert_not_reached ();
3472         }
3473
3474         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3475
3476         if (assembly->save) {
3477                 alloc_table (table, table->rows + 1);
3478                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3479                 values [MONO_METHODSPEC_METHOD] = mtoken;
3480                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3481         }
3482
3483         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3484         table->next_idx ++;
3485
3486         return token;
3487 }
3488
3489 static guint32
3490 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3491 {
3492         MonoMethodInflated *imethod;
3493         guint32 token;
3494         
3495         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3496         if (token)
3497                 return token;
3498
3499         g_assert (method->is_inflated);
3500         imethod = (MonoMethodInflated *) method;
3501
3502         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3503                 token = method_encode_methodspec (assembly, method);
3504         } else {
3505                 guint32 sig = method_encode_signature (
3506                         assembly, mono_method_signature (imethod->declaring));
3507                 token = mono_image_get_memberref_token (
3508                         assembly, &method->klass->byval_arg, method->name, sig);
3509         }
3510
3511         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3512         return token;
3513 }
3514
3515 static guint32
3516 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3517 {
3518         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3519         guint32 sig, token;
3520
3521         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3522         token = mono_image_get_memberref_token (
3523                 assembly, &m->klass->byval_arg, m->name, sig);
3524
3525         return token;
3526 }
3527
3528 static guint32
3529 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
3530 {
3531         MonoDynamicTable *table;
3532         MonoClass *klass;
3533         MonoType *type;
3534         guint32 *values;
3535         guint32 token;
3536         SigBuffer buf;
3537         int count, i;
3538
3539         /*
3540          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3541          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3542          * Because of this, we must not insert it into the `typeref' hash table.
3543          */
3544         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
3545         return_val_if_nok (error, 0);
3546         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3547         if (token)
3548                 return token;
3549
3550         sigbuffer_init (&buf, 32);
3551
3552         g_assert (tb->generic_params);
3553         klass = mono_class_from_mono_type (type);
3554
3555         if (tb->generic_container)
3556                 mono_reflection_create_generic_class (tb);
3557
3558         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3559         g_assert (klass->generic_container);
3560         sigbuffer_add_value (&buf, klass->byval_arg.type);
3561         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3562
3563         count = mono_array_length (tb->generic_params);
3564         sigbuffer_add_value (&buf, count);
3565         for (i = 0; i < count; i++) {
3566                 MonoReflectionGenericParam *gparam;
3567
3568                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3569                 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
3570                 if (!is_ok (error))
3571                         goto fail;
3572
3573                 encode_type (assembly, gparam_type, &buf);
3574         }
3575
3576         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3577
3578         if (assembly->save) {
3579                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3580                 alloc_table (table, table->rows + 1);
3581                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3582                 values [MONO_TYPESPEC_SIGNATURE] = token;
3583         }
3584         sigbuffer_free (&buf);
3585
3586         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3587         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3588         table->next_idx ++;
3589         return token;
3590 fail:
3591         sigbuffer_free (&buf);
3592         return 0;
3593 }
3594
3595 /*
3596  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3597  */
3598 static MonoType*
3599 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt, MonoError *error)
3600 {
3601         int i, count, len, pos;
3602         MonoType *t;
3603
3604         mono_error_init (error);
3605
3606         count = 0;
3607         if (modreq)
3608                 count += mono_array_length (modreq);
3609         if (modopt)
3610                 count += mono_array_length (modopt);
3611
3612         if (count == 0)
3613                 return mono_metadata_type_dup (NULL, type);
3614
3615         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3616         t = (MonoType *)g_malloc (len);
3617         memcpy (t, type, MONO_SIZEOF_TYPE);
3618
3619         t->num_mods = count;
3620         pos = 0;
3621         if (modreq) {
3622                 for (i = 0; i < mono_array_length (modreq); ++i) {
3623                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
3624                         if (!is_ok (error))
3625                                 goto fail;
3626                         t->modifiers [pos].required = 1;
3627                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3628                         pos ++;
3629                 }
3630         }
3631         if (modopt) {
3632                 for (i = 0; i < mono_array_length (modopt); ++i) {
3633                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
3634                         if (!is_ok (error))
3635                                 goto fail;
3636                         t->modifiers [pos].required = 0;
3637                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3638                         pos ++;
3639                 }
3640         }
3641
3642         return t;
3643 fail:
3644         g_free (t);
3645         return NULL;
3646 }
3647
3648 static void
3649 init_type_builder_generics (MonoObject *type)
3650 {
3651         MonoReflectionTypeBuilder *tb;
3652
3653         if (!is_sre_type_builder(mono_object_class (type)))
3654                 return;
3655         tb = (MonoReflectionTypeBuilder *)type;
3656
3657         if (tb && tb->generic_container)
3658                 mono_reflection_create_generic_class (tb);
3659 }
3660
3661 static guint32
3662 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
3663 {
3664         MonoDynamicTable *table;
3665         MonoType *custom = NULL, *type;
3666         guint32 *values;
3667         guint32 token, pclass, parent, sig;
3668         gchar *name;
3669
3670         mono_error_init (error);
3671
3672         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3673         if (token)
3674                 return token;
3675
3676         MonoType *typeb = mono_reflection_type_get_handle (fb->typeb, error);
3677         return_val_if_nok (error, 0);
3678         /* FIXME: is this call necessary? */
3679         mono_class_from_mono_type (typeb);
3680
3681         /*FIXME this is one more layer of ugliness due how types are created.*/
3682         init_type_builder_generics (fb->type);
3683
3684         /* fb->type does not include the custom modifiers */
3685         /* FIXME: We should do this in one place when a fieldbuilder is created */
3686         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3687         return_val_if_nok (error, 0);
3688
3689         if (fb->modreq || fb->modopt) {
3690                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt, error);
3691                 return_val_if_nok (error, 0);
3692         }
3693
3694         sig = fieldref_encode_signature (assembly, NULL, type);
3695         g_free (custom);
3696
3697         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb, error);
3698         return_val_if_nok (error, 0);
3699         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3700         
3701         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3702         parent >>= MONO_TYPEDEFORREF_BITS;
3703
3704         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3705
3706         name = mono_string_to_utf8 (fb->name);
3707
3708         if (assembly->save) {
3709                 alloc_table (table, table->rows + 1);
3710                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3711                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3712                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3713                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3714         }
3715
3716         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3717         table->next_idx ++;
3718         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3719         g_free (name);
3720         return token;
3721 }
3722
3723 static guint32
3724 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3725 {
3726         SigBuffer buf;
3727         guint32 nargs;
3728         guint32 i, idx;
3729
3730         mono_error_init (error);
3731
3732         if (!assembly->save)
3733                 return 0;
3734
3735         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3736         g_assert (helper->type == 2);
3737
3738         if (helper->arguments)
3739                 nargs = mono_array_length (helper->arguments);
3740         else
3741                 nargs = 0;
3742
3743         sigbuffer_init (&buf, 32);
3744
3745         /* Encode calling convention */
3746         /* Change Any to Standard */
3747         if ((helper->call_conv & 0x03) == 0x03)
3748                 helper->call_conv = 0x01;
3749         /* explicit_this implies has_this */
3750         if (helper->call_conv & 0x40)
3751                 helper->call_conv &= 0x20;
3752
3753         if (helper->call_conv == 0) { /* Unmanaged */
3754                 idx = helper->unmanaged_call_conv - 1;
3755         } else {
3756                 /* Managed */
3757                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3758                 if (helper->call_conv & 0x02) /* varargs */
3759                         idx += 0x05;
3760         }
3761
3762         sigbuffer_add_byte (&buf, idx);
3763         sigbuffer_add_value (&buf, nargs);
3764         encode_reflection_type (assembly, helper->return_type, &buf, error);
3765         if (!is_ok (error))
3766                 goto fail;
3767         for (i = 0; i < nargs; ++i) {
3768                 MonoArray *modreqs = NULL;
3769                 MonoArray *modopts = NULL;
3770                 MonoReflectionType *pt;
3771
3772                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3773                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3774                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3775                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3776
3777                 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
3778                 if (!is_ok (error))
3779                         goto fail;
3780                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3781                 encode_reflection_type (assembly, pt, &buf, error);
3782                 if (!is_ok (error))
3783                         goto fail;
3784         }
3785         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3786         sigbuffer_free (&buf);
3787
3788         return idx;
3789 fail:
3790         sigbuffer_free (&buf);
3791         return 0;
3792 }
3793
3794 static guint32 
3795 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
3796 {
3797         guint32 idx;
3798         MonoDynamicTable *table;
3799         guint32 *values;
3800
3801         mono_error_init (error);
3802
3803         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3804         idx = table->next_idx ++;
3805         table->rows ++;
3806         alloc_table (table, table->rows);
3807         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3808
3809         values [MONO_STAND_ALONE_SIGNATURE] =
3810                 mono_reflection_encode_sighelper (assembly, helper, error);
3811         return_val_if_nok (error, 0);
3812         
3813         return idx;
3814 }
3815
3816 static int
3817 reflection_cc_to_file (int call_conv) {
3818         switch (call_conv & 0x3) {
3819         case 0:
3820         case 1: return MONO_CALL_DEFAULT;
3821         case 2: return MONO_CALL_VARARG;
3822         default:
3823                 g_assert_not_reached ();
3824         }
3825         return 0;
3826 }
3827 #endif /* !DISABLE_REFLECTION_EMIT */
3828
3829 typedef struct {
3830         MonoType *parent;
3831         MonoMethodSignature *sig;
3832         char *name;
3833         guint32 token;
3834 } ArrayMethod;
3835
3836 #ifndef DISABLE_REFLECTION_EMIT
3837 static guint32
3838 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3839 {
3840         MonoError error;
3841         guint32 nparams, i;
3842         GList *tmp;
3843         char *name;
3844         MonoMethodSignature *sig;
3845         ArrayMethod *am;
3846         MonoType *mtype;
3847
3848         name = mono_string_to_utf8 (m->name);
3849         nparams = mono_array_length (m->parameters);
3850         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3851         sig->hasthis = 1;
3852         sig->sentinelpos = -1;
3853         sig->call_convention = reflection_cc_to_file (m->call_conv);
3854         sig->param_count = nparams;
3855         if (m->ret) {
3856                 sig->ret = mono_reflection_type_get_handle (m->ret, &error);
3857                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3858         } else
3859                 sig->ret = &mono_defaults.void_class->byval_arg;
3860
3861         mtype = mono_reflection_type_get_handle (m->parent, &error);
3862         mono_error_raise_exception (&error); /* FIXME don't raise here */
3863
3864         for (i = 0; i < nparams; ++i) {
3865                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i, &error);
3866                 mono_error_raise_exception (&error); /* FIXME don't raise here */
3867         }
3868
3869         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3870                 am = (ArrayMethod *)tmp->data;
3871                 if (strcmp (name, am->name) == 0 && 
3872                                 mono_metadata_type_equal (am->parent, mtype) &&
3873                                 mono_metadata_signature_equal (am->sig, sig)) {
3874                         g_free (name);
3875                         g_free (sig);
3876                         m->table_idx = am->token & 0xffffff;
3877                         return am->token;
3878                 }
3879         }
3880         am = g_new0 (ArrayMethod, 1);
3881         am->name = name;
3882         am->sig = sig;
3883         am->parent = mtype;
3884         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3885                 method_encode_signature (assembly, sig));
3886         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3887         m->table_idx = am->token & 0xffffff;
3888         return am->token;
3889 }
3890
3891 /*
3892  * Insert into the metadata tables all the info about the TypeBuilder tb.
3893  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3894  */
3895 static gboolean
3896 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3897 {
3898         MonoDynamicTable *table;
3899         guint *values;
3900         int i, is_object = 0, is_system = 0;
3901         char *n;
3902
3903         mono_error_init (error);
3904
3905         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3906         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3907         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3908         n = mono_string_to_utf8 (tb->name);
3909         if (strcmp (n, "Object") == 0)
3910                 is_object++;
3911         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3912         g_free (n);
3913         n = mono_string_to_utf8 (tb->nspace);
3914         if (strcmp (n, "System") == 0)
3915                 is_system++;
3916         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3917         g_free (n);
3918         if (tb->parent && !(is_system && is_object) && 
3919                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3920                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, error);
3921                 return_val_if_nok (error, FALSE);
3922                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, parent_type);
3923         } else {
3924                 values [MONO_TYPEDEF_EXTENDS] = 0;
3925         }
3926         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3927         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3928
3929         /*
3930          * if we have explicitlayout or sequentiallayouts, output data in the
3931          * ClassLayout table.
3932          */
3933         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3934                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3935                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3936                 table->rows++;
3937                 alloc_table (table, table->rows);
3938                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3939                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3940                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3941                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3942         }
3943
3944         /* handle interfaces */
3945         if (tb->interfaces) {
3946                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3947                 i = table->rows;
3948                 table->rows += mono_array_length (tb->interfaces);
3949                 alloc_table (table, table->rows);
3950                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3951                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3952                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3953                         MonoType *iface_type = mono_reflection_type_get_handle (iface, error);
3954                         return_val_if_nok (error, FALSE);
3955                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3956                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface_type);
3957                         values += MONO_INTERFACEIMPL_SIZE;
3958                 }
3959         }
3960
3961         /* handle fields */
3962         if (tb->fields) {
3963                 table = &assembly->tables [MONO_TABLE_FIELD];
3964                 table->rows += tb->num_fields;
3965                 alloc_table (table, table->rows);
3966                 for (i = 0; i < tb->num_fields; ++i) {
3967                         mono_image_get_field_info (
3968                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly, error);
3969                         return_val_if_nok (error, FALSE);
3970                 }
3971         }
3972
3973         /* handle constructors */
3974         if (tb->ctors) {
3975                 table = &assembly->tables [MONO_TABLE_METHOD];
3976                 table->rows += mono_array_length (tb->ctors);
3977                 alloc_table (table, table->rows);
3978                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3979                         if (!mono_image_get_ctor_info (domain,
3980                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3981                                                        assembly, error))
3982                                 return FALSE;
3983                 }
3984         }
3985
3986         /* handle methods */
3987         if (tb->methods) {
3988                 table = &assembly->tables [MONO_TABLE_METHOD];
3989                 table->rows += tb->num_methods;
3990                 alloc_table (table, table->rows);
3991                 for (i = 0; i < tb->num_methods; ++i) {
3992                         if (!mono_image_get_method_info (
3993                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3994                                 return FALSE;
3995                 }
3996         }
3997
3998         /* Do the same with properties etc.. */
3999         if (tb->events && mono_array_length (tb->events)) {
4000                 table = &assembly->tables [MONO_TABLE_EVENT];
4001                 table->rows += mono_array_length (tb->events);
4002                 alloc_table (table, table->rows);
4003                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
4004                 table->rows ++;
4005                 alloc_table (table, table->rows);
4006                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
4007                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
4008                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
4009                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4010                         mono_image_get_event_info (
4011                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly, error);
4012                         return_val_if_nok (error, FALSE);
4013                 }
4014         }
4015         if (tb->properties && mono_array_length (tb->properties)) {
4016                 table = &assembly->tables [MONO_TABLE_PROPERTY];
4017                 table->rows += mono_array_length (tb->properties);
4018                 alloc_table (table, table->rows);
4019                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
4020                 table->rows ++;
4021                 alloc_table (table, table->rows);
4022                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
4023                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
4024                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
4025                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4026                         mono_image_get_property_info (
4027                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly, error);
4028                         return_val_if_nok (error, FALSE);
4029                 }
4030         }
4031
4032         /* handle generic parameters */
4033         if (tb->generic_params) {
4034                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
4035                 table->rows += mono_array_length (tb->generic_params);
4036                 alloc_table (table, table->rows);
4037                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
4038                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
4039
4040                         mono_image_get_generic_param_info (
4041                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
4042                 }
4043         }
4044
4045         mono_image_add_decl_security (assembly, 
4046                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
4047
4048         if (tb->subtypes) {
4049                 MonoDynamicTable *ntable;
4050                 
4051                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4052                 ntable->rows += mono_array_length (tb->subtypes);
4053                 alloc_table (ntable, ntable->rows);
4054                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
4055
4056                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4057                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
4058
4059                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
4060                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
4061                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
4062                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
4063                                 mono_string_to_utf8 (tb->name), tb->table_idx,
4064                                 ntable->next_idx, ntable->rows);*/
4065                         values += MONO_NESTED_CLASS_SIZE;
4066                         ntable->next_idx++;
4067                 }
4068         }
4069
4070         return TRUE;
4071 }
4072 #endif
4073
4074 static void
4075 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
4076 {
4077         int i;
4078
4079         mono_ptr_array_append (*types, type);
4080
4081         if (!type->subtypes)
4082                 return;
4083
4084         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
4085                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
4086                 collect_types (types, subtype);
4087         }
4088 }
4089
4090 static gint
4091 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
4092 {
4093         if ((*type1)->table_idx < (*type2)->table_idx)
4094                 return -1;
4095         else
4096                 if ((*type1)->table_idx > (*type2)->table_idx)
4097                         return 1;
4098         else
4099                 return 0;
4100 }
4101
4102 static gboolean
4103 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
4104         int i;
4105
4106         mono_error_init (error);
4107         if (!pinfo)
4108                 return TRUE;
4109         for (i = 0; i < mono_array_length (pinfo); ++i) {
4110                 MonoReflectionParamBuilder *pb;
4111                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
4112                 if (!pb)
4113                         continue;
4114                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
4115                         return FALSE;
4116         }
4117
4118         return TRUE;
4119 }
4120
4121 static gboolean
4122 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
4123         int i;
4124
4125         mono_error_init (error);
4126         
4127         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
4128                 return FALSE;
4129         if (tb->fields) {
4130                 for (i = 0; i < tb->num_fields; ++i) {
4131                         MonoReflectionFieldBuilder* fb;
4132                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
4133                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4134                                 return FALSE;
4135                 }
4136         }
4137         if (tb->events) {
4138                 for (i = 0; i < mono_array_length (tb->events); ++i) {
4139                         MonoReflectionEventBuilder* eb;
4140                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
4141                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
4142                                 return FALSE;
4143                 }
4144         }
4145         if (tb->properties) {
4146                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
4147                         MonoReflectionPropertyBuilder* pb;
4148                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
4149                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
4150                                 return FALSE;
4151                 }
4152         }
4153         if (tb->ctors) {
4154                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
4155                         MonoReflectionCtorBuilder* cb;
4156                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
4157                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
4158                             !params_add_cattrs (assembly, cb->pinfo, error))
4159                                 return FALSE;
4160                 }
4161         }
4162
4163         if (tb->methods) {
4164                 for (i = 0; i < tb->num_methods; ++i) {
4165                         MonoReflectionMethodBuilder* mb;
4166                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
4167                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4168                             !params_add_cattrs (assembly, mb->pinfo, error))
4169                                 return FALSE;
4170                 }
4171         }
4172
4173         if (tb->subtypes) {
4174                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
4175                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
4176                                 return FALSE;
4177                 }
4178         }
4179
4180         return TRUE;
4181 }
4182
4183 static gboolean
4184 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
4185 {
4186         int i;
4187         
4188         mono_error_init (error);
4189
4190         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4191                 return FALSE;
4192
4193         if (moduleb->global_methods) {
4194                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4195                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4196                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4197                             !params_add_cattrs (assembly, mb->pinfo, error))
4198                                 return FALSE;
4199                 }
4200         }
4201
4202         if (moduleb->global_fields) {
4203                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4204                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4205                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4206                                 return FALSE;
4207                 }
4208         }
4209         
4210         if (moduleb->types) {
4211                 for (i = 0; i < moduleb->num_types; ++i) {
4212                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4213                                 return FALSE;
4214                 }
4215         }
4216
4217         return TRUE;
4218 }
4219
4220 static void
4221 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4222 {
4223         MonoDynamicTable *table;
4224         guint32 *values;
4225         char blob_size [6];
4226         guchar hash [20];
4227         char *b = blob_size;
4228         char *dir, *path;
4229
4230         table = &assembly->tables [MONO_TABLE_FILE];
4231         table->rows++;
4232         alloc_table (table, table->rows);
4233         values = table->values + table->next_idx * MONO_FILE_SIZE;
4234         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4235         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4236         if (image_is_dynamic (module->image)) {
4237                 /* This depends on the fact that the main module is emitted last */
4238                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4239                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4240         } else {
4241                 dir = NULL;
4242                 path = g_strdup (module->image->name);
4243         }
4244         mono_sha1_get_digest_from_file (path, hash);
4245         g_free (dir);
4246         g_free (path);
4247         mono_metadata_encode_value (20, b, &b);
4248         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4249         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4250         table->next_idx ++;
4251 }
4252
4253 static void
4254 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4255 {
4256         MonoDynamicTable *table;
4257         int i;
4258
4259         table = &assembly->tables [MONO_TABLE_MODULE];
4260         mb->table_idx = table->next_idx ++;
4261         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4262         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4263         i /= 16;
4264         ++i;
4265         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4266         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4267         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4268         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4269 }
4270
4271 static guint32
4272 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4273         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4274 {
4275         MonoDynamicTable *table;
4276         guint32 *values;
4277         guint32 visib, res;
4278
4279         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4280         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4281                 return 0;
4282
4283         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4284         table->rows++;
4285         alloc_table (table, table->rows);
4286         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4287
4288         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4289         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4290         if (klass->nested_in)
4291                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4292         else
4293                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4294         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4295         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4296
4297         res = table->next_idx;
4298
4299         table->next_idx ++;
4300
4301         /* Emit nested types */
4302         if (klass->ext && klass->ext->nested_classes) {
4303                 GList *tmp;
4304
4305                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4306                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4307         }
4308
4309         return res;
4310 }
4311
4312 static void
4313 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4314         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4315 {
4316         MonoError error;
4317         MonoClass *klass;
4318         guint32 idx, i;
4319
4320         MonoType *t = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
4321         mono_error_raise_exception (&error); /* FIXME don't raise here */
4322
4323         klass = mono_class_from_mono_type (t);
4324
4325         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4326
4327         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4328                                                                                                    parent_index, assembly);
4329
4330         /* 
4331          * Emit nested types
4332          * We need to do this ourselves since klass->nested_classes is not set up.
4333          */
4334         if (tb->subtypes) {
4335                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4336                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4337         }
4338 }
4339
4340 static void
4341 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4342         guint32 module_index, MonoDynamicImage *assembly)
4343 {
4344         MonoImage *image = module->image;
4345         MonoTableInfo  *t;
4346         guint32 i;
4347
4348         t = &image->tables [MONO_TABLE_TYPEDEF];
4349
4350         for (i = 0; i < t->rows; ++i) {
4351                 MonoError error;
4352                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4353                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4354
4355                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4356                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4357         }
4358 }
4359
4360 static void
4361 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4362 {
4363         MonoDynamicTable *table;
4364         guint32 *values;
4365         guint32 scope, scope_idx, impl, current_idx;
4366         gboolean forwarder = TRUE;
4367         gpointer iter = NULL;
4368         MonoClass *nested;
4369
4370         if (klass->nested_in) {
4371                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4372                 forwarder = FALSE;
4373         } else {
4374                 scope = resolution_scope_from_image (assembly, klass->image);
4375                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4376                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4377                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4378         }
4379
4380         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4381
4382         table->rows++;
4383         alloc_table (table, table->rows);
4384         current_idx = table->next_idx;
4385         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4386
4387         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4388         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4389         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4390         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4391         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4392
4393         table->next_idx++;
4394
4395         while ((nested = mono_class_get_nested_types (klass, &iter)))
4396                 add_exported_type (assemblyb, assembly, nested, current_idx);
4397 }
4398
4399 static void
4400 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4401 {
4402         MonoError error;
4403         MonoClass *klass;
4404         int i;
4405
4406         if (!assemblyb->type_forwarders)
4407                 return;
4408
4409         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4410                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4411                 MonoType *type;
4412                 if (!t)
4413                         continue;
4414
4415                 type = mono_reflection_type_get_handle (t, &error);
4416                 mono_error_assert_ok (&error);
4417                 g_assert (type);
4418
4419                 klass = mono_class_from_mono_type (type);
4420
4421                 add_exported_type (assemblyb, assembly, klass, 0);
4422         }
4423 }
4424
4425 #define align_pointer(base,p)\
4426         do {\
4427                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4428                 if (__diff & 3)\
4429                         (p) += 4 - (__diff & 3);\
4430         } while (0)
4431
4432 static int
4433 compare_constants (const void *a, const void *b)
4434 {
4435         const guint32 *a_values = (const guint32 *)a;
4436         const guint32 *b_values = (const guint32 *)b;
4437         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4438 }
4439
4440 static int
4441 compare_semantics (const void *a, const void *b)
4442 {
4443         const guint32 *a_values = (const guint32 *)a;
4444         const guint32 *b_values = (const guint32 *)b;
4445         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4446         if (assoc)
4447                 return assoc;
4448         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4449 }
4450
4451 static int
4452 compare_custom_attrs (const void *a, const void *b)
4453 {
4454         const guint32 *a_values = (const guint32 *)a;
4455         const guint32 *b_values = (const guint32 *)b;
4456
4457         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4458 }
4459
4460 static int
4461 compare_field_marshal (const void *a, const void *b)
4462 {
4463         const guint32 *a_values = (const guint32 *)a;
4464         const guint32 *b_values = (const guint32 *)b;
4465
4466         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4467 }
4468
4469 static int
4470 compare_nested (const void *a, const void *b)
4471 {
4472         const guint32 *a_values = (const guint32 *)a;
4473         const guint32 *b_values = (const guint32 *)b;
4474
4475         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4476 }
4477
4478 static int
4479 compare_genericparam (const void *a, const void *b)
4480 {
4481         MonoError error;
4482         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4483         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4484
4485         if ((*b_entry)->owner == (*a_entry)->owner) {
4486                 MonoType *a_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam, &error);
4487                 mono_error_assert_ok (&error);
4488                 MonoType *b_type = mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam, &error);
4489                 mono_error_assert_ok (&error);
4490                 return 
4491                         mono_type_get_generic_param_num (a_type) -
4492                         mono_type_get_generic_param_num (b_type);
4493         } else
4494                 return (*a_entry)->owner - (*b_entry)->owner;
4495 }
4496
4497 static int
4498 compare_declsecurity_attrs (const void *a, const void *b)
4499 {
4500         const guint32 *a_values = (const guint32 *)a;
4501         const guint32 *b_values = (const guint32 *)b;
4502
4503         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4504 }
4505
4506 static int
4507 compare_interface_impl (const void *a, const void *b)
4508 {
4509         const guint32 *a_values = (const guint32 *)a;
4510         const guint32 *b_values = (const guint32 *)b;
4511
4512         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4513         if (klass)
4514                 return klass;
4515
4516         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4517 }
4518
4519 static void
4520 pad_heap (MonoDynamicStream *sh)
4521 {
4522         if (sh->index & 3) {
4523                 int sz = 4 - (sh->index & 3);
4524                 memset (sh->data + sh->index, 0, sz);
4525                 sh->index += sz;
4526         }
4527 }
4528
4529 struct StreamDesc {
4530         const char *name;
4531         MonoDynamicStream *stream;
4532 };
4533
4534 /*
4535  * build_compressed_metadata() fills in the blob of data that represents the 
4536  * raw metadata as it will be saved in the PE file. The five streams are output 
4537  * and the metadata tables are comnpressed from the guint32 array representation, 
4538  * to the compressed on-disk format.
4539  */
4540 static gboolean
4541 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4542 {
4543         MonoDynamicTable *table;
4544         int i;
4545         guint64 valid_mask = 0;
4546         guint64 sorted_mask;
4547         guint32 heapt_size = 0;
4548         guint32 meta_size = 256; /* allow for header and other stuff */
4549         guint32 table_offset;
4550         guint32 ntables = 0;
4551         guint64 *int64val;
4552         guint32 *int32val;
4553         guint16 *int16val;
4554         MonoImage *meta;
4555         unsigned char *p;
4556         struct StreamDesc stream_desc [5];
4557
4558         mono_error_init (error);
4559
4560         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4561         for (i = 0; i < assembly->gen_params->len; i++) {
4562                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4563                 if (!write_generic_param_entry (assembly, entry, error))
4564                         return FALSE;
4565         }
4566
4567         stream_desc [0].name  = "#~";
4568         stream_desc [0].stream = &assembly->tstream;
4569         stream_desc [1].name  = "#Strings";
4570         stream_desc [1].stream = &assembly->sheap;
4571         stream_desc [2].name  = "#US";
4572         stream_desc [2].stream = &assembly->us;
4573         stream_desc [3].name  = "#Blob";
4574         stream_desc [3].stream = &assembly->blob;
4575         stream_desc [4].name  = "#GUID";
4576         stream_desc [4].stream = &assembly->guid;
4577         
4578         /* tables that are sorted */
4579         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4580                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4581                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4582                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4583                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4584                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4585                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4586         
4587         /* Compute table sizes */
4588         /* the MonoImage has already been created in mono_image_basic_init() */
4589         meta = &assembly->image;
4590
4591         /* sizes should be multiple of 4 */
4592         pad_heap (&assembly->blob);
4593         pad_heap (&assembly->guid);
4594         pad_heap (&assembly->sheap);
4595         pad_heap (&assembly->us);
4596
4597         /* Setup the info used by compute_sizes () */
4598         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4599         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4600         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4601
4602         meta_size += assembly->blob.index;
4603         meta_size += assembly->guid.index;
4604         meta_size += assembly->sheap.index;
4605         meta_size += assembly->us.index;
4606
4607         for (i=0; i < MONO_TABLE_NUM; ++i)
4608                 meta->tables [i].rows = assembly->tables [i].rows;
4609         
4610         for (i = 0; i < MONO_TABLE_NUM; i++){
4611                 if (meta->tables [i].rows == 0)
4612                         continue;
4613                 valid_mask |= (guint64)1 << i;
4614                 ntables ++;
4615                 meta->tables [i].row_size = mono_metadata_compute_size (
4616                         meta, i, &meta->tables [i].size_bitfield);
4617                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4618         }
4619         heapt_size += 24; /* #~ header size */
4620         heapt_size += ntables * 4;
4621         /* make multiple of 4 */
4622         heapt_size += 3;
4623         heapt_size &= ~3;
4624         meta_size += heapt_size;
4625         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4626         p = (unsigned char*)meta->raw_metadata;
4627         /* the metadata signature */
4628         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4629         /* version numbers and 4 bytes reserved */
4630         int16val = (guint16*)p;
4631         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4632         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4633         p += 8;
4634         /* version string */
4635         int32val = (guint32*)p;
4636         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4637         p += 4;
4638         memcpy (p, meta->version, strlen (meta->version));
4639         p += GUINT32_FROM_LE (*int32val);
4640         align_pointer (meta->raw_metadata, p);
4641         int16val = (guint16*)p;
4642         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4643         *int16val = GUINT16_TO_LE (5); /* number of streams */
4644         p += 4;
4645
4646         /*
4647          * write the stream info.
4648          */
4649         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4650         table_offset += 3; table_offset &= ~3;
4651
4652         assembly->tstream.index = heapt_size;
4653         for (i = 0; i < 5; ++i) {
4654                 int32val = (guint32*)p;
4655                 stream_desc [i].stream->offset = table_offset;
4656                 *int32val++ = GUINT32_TO_LE (table_offset);
4657                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4658                 table_offset += GUINT32_FROM_LE (*int32val);
4659                 table_offset += 3; table_offset &= ~3;
4660                 p += 8;
4661                 strcpy ((char*)p, stream_desc [i].name);
4662                 p += strlen (stream_desc [i].name) + 1;
4663                 align_pointer (meta->raw_metadata, p);
4664         }
4665         /* 
4666          * now copy the data, the table stream header and contents goes first.
4667          */
4668         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4669         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4670         int32val = (guint32*)p;
4671         *int32val = GUINT32_TO_LE (0); /* reserved */
4672         p += 4;
4673
4674         *p++ = 2; /* version */
4675         *p++ = 0;
4676
4677         if (meta->idx_string_wide)
4678                 *p |= 0x01;
4679         if (meta->idx_guid_wide)
4680                 *p |= 0x02;
4681         if (meta->idx_blob_wide)
4682                 *p |= 0x04;
4683         ++p;
4684         *p++ = 1; /* reserved */
4685         int64val = (guint64*)p;
4686         *int64val++ = GUINT64_TO_LE (valid_mask);
4687         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4688         p += 16;
4689         int32val = (guint32*)p;
4690         for (i = 0; i < MONO_TABLE_NUM; i++){
4691                 if (meta->tables [i].rows == 0)
4692                         continue;
4693                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4694         }
4695         p = (unsigned char*)int32val;
4696
4697         /* sort the tables that still need sorting */
4698         table = &assembly->tables [MONO_TABLE_CONSTANT];
4699         if (table->rows)
4700                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4701         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4702         if (table->rows)
4703                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4704         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4705         if (table->rows)
4706                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4707         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4708         if (table->rows)
4709                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4710         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4711         if (table->rows)
4712                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4713         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4714         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4715         if (table->rows)
4716                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4717         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4718         if (table->rows)
4719                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4720
4721         /* compress the tables */
4722         for (i = 0; i < MONO_TABLE_NUM; i++){
4723                 int row, col;
4724                 guint32 *values;
4725                 guint32 bitfield = meta->tables [i].size_bitfield;
4726                 if (!meta->tables [i].rows)
4727                         continue;
4728                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4729                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4730                 meta->tables [i].base = (char*)p;
4731                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4732                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4733                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4734                                 switch (mono_metadata_table_size (bitfield, col)) {
4735                                 case 1:
4736                                         *p++ = values [col];
4737                                         break;
4738                                 case 2:
4739                                         *p++ = values [col] & 0xff;
4740                                         *p++ = (values [col] >> 8) & 0xff;
4741                                         break;
4742                                 case 4:
4743                                         *p++ = values [col] & 0xff;
4744                                         *p++ = (values [col] >> 8) & 0xff;
4745                                         *p++ = (values [col] >> 16) & 0xff;
4746                                         *p++ = (values [col] >> 24) & 0xff;
4747                                         break;
4748                                 default:
4749                                         g_assert_not_reached ();
4750                                 }
4751                         }
4752                 }
4753                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4754         }
4755         
4756         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4757         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4758         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4759         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4760         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4761
4762         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4763
4764         return TRUE;
4765 }
4766
4767 /*
4768  * Some tables in metadata need to be sorted according to some criteria, but
4769  * when methods and fields are first created with reflection, they may be assigned a token
4770  * that doesn't correspond to the final token they will get assigned after the sorting.
4771  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4772  * with the reflection objects that represent them. Once all the tables are set up, the 
4773  * reflection objects will contains the correct table index. fixup_method() will fixup the
4774  * tokens for the method with ILGenerator @ilgen.
4775  */
4776 static void
4777 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4778 {
4779         guint32 code_idx = GPOINTER_TO_UINT (value);
4780         MonoReflectionILTokenInfo *iltoken;
4781         MonoReflectionFieldBuilder *field;
4782         MonoReflectionCtorBuilder *ctor;
4783         MonoReflectionMethodBuilder *method;
4784         MonoReflectionTypeBuilder *tb;
4785         MonoReflectionArrayMethod *am;
4786         guint32 i, idx = 0;
4787         unsigned char *target;
4788
4789         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4790                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4791                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4792                 switch (target [3]) {
4793                 case MONO_TABLE_FIELD:
4794                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4795                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4796                                 idx = field->table_idx;
4797                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4798                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4799                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4800                         } else {
4801                                 g_assert_not_reached ();
4802                         }
4803                         break;
4804                 case MONO_TABLE_METHOD:
4805                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4806                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4807                                 idx = method->table_idx;
4808                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4809                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4810                                 idx = ctor->table_idx;
4811                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4812                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4813                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4814                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4815                         } else {
4816                                 g_assert_not_reached ();
4817                         }
4818                         break;
4819                 case MONO_TABLE_TYPEDEF:
4820                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4821                                 g_assert_not_reached ();
4822                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4823                         idx = tb->table_idx;
4824                         break;
4825                 case MONO_TABLE_MEMBERREF:
4826                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4827                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4828                                 idx = am->table_idx;
4829                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4830                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4831                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4832                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4833                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4834                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4835                                 continue;
4836                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4837                                 continue;
4838                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4839                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4840                                 g_assert (is_field_on_inst (f));
4841                                 continue;
4842                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4843                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4844                                 continue;
4845                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4846                                 continue;
4847                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4848                                 continue;
4849                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4850                                 continue;
4851                         } else {
4852                                 g_assert_not_reached ();
4853                         }
4854                         break;
4855                 case MONO_TABLE_METHODSPEC:
4856                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4857                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4858                                 g_assert (mono_method_signature (m)->generic_param_count);
4859                                 continue;
4860                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4861                                 continue;
4862                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4863                                 continue;
4864                         } else {
4865                                 g_assert_not_reached ();
4866                         }
4867                         break;
4868                 default:
4869                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4870                 }
4871                 target [0] = idx & 0xff;
4872                 target [1] = (idx >> 8) & 0xff;
4873                 target [2] = (idx >> 16) & 0xff;
4874         }
4875 }
4876
4877 /*
4878  * fixup_cattrs:
4879  *
4880  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4881  * value is not known when the table is emitted.
4882  */
4883 static void
4884 fixup_cattrs (MonoDynamicImage *assembly)
4885 {
4886         MonoDynamicTable *table;
4887         guint32 *values;
4888         guint32 type, i, idx, token;
4889         MonoObject *ctor;
4890
4891         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4892
4893         for (i = 0; i < table->rows; ++i) {
4894                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4895
4896                 type = values [MONO_CUSTOM_ATTR_TYPE];
4897                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4898                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4899                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4900                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4901                         g_assert (ctor);
4902
4903                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4904                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4905                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4906                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4907                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4908                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4909                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4910                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4911                         }
4912                 }
4913         }
4914 }
4915
4916 static void
4917 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4918 {
4919         MonoDynamicTable *table;
4920         guint32 *values;
4921
4922         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4923         table->rows++;
4924         alloc_table (table, table->rows);
4925         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4926         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4927         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4928         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4929         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4930         table->next_idx++;
4931 }
4932
4933 static void
4934 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4935 {
4936         MonoDynamicTable *table;
4937         guint32 *values;
4938         char blob_size [6];
4939         guchar hash [20];
4940         char *b = blob_size;
4941         char *name, *sname;
4942         guint32 idx, offset;
4943
4944         if (rsrc->filename) {
4945                 name = mono_string_to_utf8 (rsrc->filename);
4946                 sname = g_path_get_basename (name);
4947         
4948                 table = &assembly->tables [MONO_TABLE_FILE];
4949                 table->rows++;
4950                 alloc_table (table, table->rows);
4951                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4952                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4953                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4954                 g_free (sname);
4955
4956                 mono_sha1_get_digest_from_file (name, hash);
4957                 mono_metadata_encode_value (20, b, &b);
4958                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4959                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4960                 g_free (name);
4961                 idx = table->next_idx++;
4962                 rsrc->offset = 0;
4963                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4964         } else {
4965                 char sizebuf [4];
4966                 char *data;
4967                 guint len;
4968                 if (rsrc->data) {
4969                         data = mono_array_addr (rsrc->data, char, 0);
4970                         len = mono_array_length (rsrc->data);
4971                 } else {
4972                         data = NULL;
4973                         len = 0;
4974                 }
4975                 offset = len;
4976                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4977                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4978                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4979                 mono_image_add_stream_data (&assembly->resources, data, len);
4980
4981                 if (!mb->is_main)
4982                         /* 
4983                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4984                          * the main module, but that needs to reference the FILE table
4985                          * which isn't emitted yet.
4986                          */
4987                         return;
4988                 else
4989                         idx = 0;
4990         }
4991
4992         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4993 }
4994
4995 static void
4996 set_version_from_string (MonoString *version, guint32 *values)
4997 {
4998         gchar *ver, *p, *str;
4999         guint32 i;
5000         
5001         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
5002         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
5003         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
5004         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
5005         if (!version)
5006                 return;
5007         ver = str = mono_string_to_utf8 (version);
5008         for (i = 0; i < 4; ++i) {
5009                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
5010                 switch (*p) {
5011                 case '.':
5012                         p++;
5013                         break;
5014                 case '*':
5015                         /* handle Revision and Build */
5016                         p++;
5017                         break;
5018                 }
5019                 ver = p;
5020         }
5021         g_free (str);
5022 }
5023
5024 static guint32
5025 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
5026         gsize len;
5027         guint32 token = 0;
5028         char blob_size [6];
5029         char *b = blob_size;
5030
5031         if (!pkey)
5032                 return token;
5033
5034         len = mono_array_length (pkey);
5035         mono_metadata_encode_value (len, b, &b);
5036         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
5037         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
5038
5039         assembly->public_key = (guint8 *)g_malloc (len);
5040         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
5041         assembly->public_key_len = len;
5042
5043         /* Special case: check for ECMA key (16 bytes) */
5044         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
5045                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
5046                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
5047         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
5048                 /* minimum key size (in 2.0) is 384 bits */
5049                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
5050         } else {
5051                 /* FIXME - verifier */
5052                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
5053                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
5054         }
5055         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
5056
5057         return token;
5058 }
5059
5060 static void
5061 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
5062 {
5063         MonoDynamicTable *table;
5064         MonoDynamicImage *assembly;
5065         MonoReflectionAssemblyBuilder *assemblyb;
5066         MonoDomain *domain;
5067         guint32 *values;
5068         int i;
5069         guint32 module_index;
5070
5071         assemblyb = moduleb->assemblyb;
5072         assembly = moduleb->dynamic_image;
5073         domain = mono_object_domain (assemblyb);
5074
5075         /* Emit ASSEMBLY table */
5076         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
5077         alloc_table (table, 1);
5078         values = table->values + MONO_ASSEMBLY_SIZE;
5079         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
5080         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
5081         if (assemblyb->culture) {
5082                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
5083         } else {
5084                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
5085         }
5086         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
5087         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
5088         set_version_from_string (assemblyb->version, values);
5089
5090         /* Emit FILE + EXPORTED_TYPE table */
5091         module_index = 0;
5092         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5093                 int j;
5094                 MonoReflectionModuleBuilder *file_module = 
5095                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5096                 if (file_module != moduleb) {
5097                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
5098                         module_index ++;
5099                         if (file_module->types) {
5100                                 for (j = 0; j < file_module->num_types; ++j) {
5101                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
5102                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
5103                                 }
5104                         }
5105                 }
5106         }
5107         if (assemblyb->loaded_modules) {
5108                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
5109                         MonoReflectionModule *file_module = 
5110                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
5111                         mono_image_fill_file_table (domain, file_module, assembly);
5112                         module_index ++;
5113                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
5114                 }
5115         }
5116         if (assemblyb->type_forwarders)
5117                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
5118
5119         /* Emit MANIFESTRESOURCE table */
5120         module_index = 0;
5121         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
5122                 int j;
5123                 MonoReflectionModuleBuilder *file_module = 
5124                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
5125                 /* The table for the main module is emitted later */
5126                 if (file_module != moduleb) {
5127                         module_index ++;
5128                         if (file_module->resources) {
5129                                 int len = mono_array_length (file_module->resources);
5130                                 for (j = 0; j < len; ++j) {
5131                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
5132                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
5133                                 }
5134                         }
5135                 }
5136         }               
5137 }
5138
5139 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5140
5141 /*
5142  * mono_image_build_metadata() will fill the info in all the needed metadata tables
5143  * for the modulebuilder @moduleb.
5144  * At the end of the process, method and field tokens are fixed up and the 
5145  * on-disk compressed metadata representation is created.
5146  * Return TRUE on success, or FALSE on failure and sets @error
5147  */
5148 gboolean
5149 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5150 {
5151         MonoDynamicTable *table;
5152         MonoDynamicImage *assembly;
5153         MonoReflectionAssemblyBuilder *assemblyb;
5154         MonoDomain *domain;
5155         MonoPtrArray types;
5156         guint32 *values;
5157         int i, j;
5158
5159         mono_error_init (error);
5160
5161         assemblyb = moduleb->assemblyb;
5162         assembly = moduleb->dynamic_image;
5163         domain = mono_object_domain (assemblyb);
5164
5165         if (assembly->text_rva)
5166                 return TRUE;
5167
5168         assembly->text_rva = START_TEXT_RVA;
5169
5170         if (moduleb->is_main) {
5171                 mono_image_emit_manifest (moduleb);
5172         }
5173
5174         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5175         table->rows = 1; /* .<Module> */
5176         table->next_idx++;
5177         alloc_table (table, table->rows);
5178         /*
5179          * Set the first entry.
5180          */
5181         values = table->values + table->columns;
5182         values [MONO_TYPEDEF_FLAGS] = 0;
5183         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
5184         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
5185         values [MONO_TYPEDEF_EXTENDS] = 0;
5186         values [MONO_TYPEDEF_FIELD_LIST] = 1;
5187         values [MONO_TYPEDEF_METHOD_LIST] = 1;
5188
5189         /* 
5190          * handle global methods 
5191          * FIXME: test what to do when global methods are defined in multiple modules.
5192          */
5193         if (moduleb->global_methods) {
5194                 table = &assembly->tables [MONO_TABLE_METHOD];
5195                 table->rows += mono_array_length (moduleb->global_methods);
5196                 alloc_table (table, table->rows);
5197                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5198                         if (!mono_image_get_method_info (
5199                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5200                                 goto leave;
5201                 }
5202         }
5203         if (moduleb->global_fields) {
5204                 table = &assembly->tables [MONO_TABLE_FIELD];
5205                 table->rows += mono_array_length (moduleb->global_fields);
5206                 alloc_table (table, table->rows);
5207                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
5208                         mono_image_get_field_info (
5209                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly,
5210                                 error);
5211                         if (!is_ok (error))
5212                                 goto leave;
5213                 }
5214         }
5215
5216         table = &assembly->tables [MONO_TABLE_MODULE];
5217         alloc_table (table, 1);
5218         mono_image_fill_module_table (domain, moduleb, assembly);
5219
5220         /* Collect all types into a list sorted by their table_idx */
5221         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5222
5223         if (moduleb->types)
5224                 for (i = 0; i < moduleb->num_types; ++i) {
5225                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5226                         collect_types (&types, type);
5227                 }
5228
5229         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5230         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5231         table->rows += mono_ptr_array_size (types);
5232         alloc_table (table, table->rows);
5233
5234         /*
5235          * Emit type names + namespaces at one place inside the string heap,
5236          * so load_class_names () needs to touch fewer pages.
5237          */
5238         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5239                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5240                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5241         }
5242         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5243                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5244                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5245         }
5246
5247         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5248                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5249                 if (!mono_image_get_type_info (domain, type, assembly, error))
5250                         goto leave_types;
5251         }
5252
5253         /* 
5254          * table->rows is already set above and in mono_image_fill_module_table.
5255          */
5256         /* add all the custom attributes at the end, once all the indexes are stable */
5257         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5258                 goto leave_types;
5259
5260         /* CAS assembly permissions */
5261         if (assemblyb->permissions_minimum)
5262                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5263         if (assemblyb->permissions_optional)
5264                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5265         if (assemblyb->permissions_refused)
5266                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5267
5268         if (!module_add_cattrs (assembly, moduleb, error))
5269                 goto leave_types;
5270
5271         /* fixup tokens */
5272         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5273
5274         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5275          * the final tokens and don't need another fixup pass. */
5276
5277         if (moduleb->global_methods) {
5278                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5279                         MonoReflectionMethodBuilder *mb = mono_array_get (
5280                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5281                         if (!mono_image_add_methodimpl (assembly, mb, error))
5282                                 goto leave_types;
5283                 }
5284         }
5285
5286         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5287                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5288                 if (type->methods) {
5289                         for (j = 0; j < type->num_methods; ++j) {
5290                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5291                                         type->methods, MonoReflectionMethodBuilder*, j);
5292
5293                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5294                                         goto leave_types;
5295                         }
5296                 }
5297         }
5298
5299         fixup_cattrs (assembly);
5300
5301 leave_types:
5302         mono_ptr_array_destroy (types);
5303 leave:
5304
5305         return mono_error_ok (error);
5306 }
5307
5308 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5309
5310 gboolean
5311 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5312 {
5313         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5314 }
5315
5316 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5317
5318
5319 typedef struct {
5320         guint32 import_lookup_table;
5321         guint32 timestamp;
5322         guint32 forwarder;
5323         guint32 name_rva;
5324         guint32 import_address_table_rva;
5325 } MonoIDT;
5326
5327 typedef struct {
5328         guint32 name_rva;
5329         guint32 flags;
5330 } MonoILT;
5331
5332 #ifndef DISABLE_REFLECTION_EMIT
5333
5334 /*
5335  * mono_image_insert_string:
5336  * @module: module builder object
5337  * @str: a string
5338  *
5339  * Insert @str into the user string stream of @module.
5340  */
5341 guint32
5342 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5343 {
5344         MonoDynamicImage *assembly;
5345         guint32 idx;
5346         char buf [16];
5347         char *b = buf;
5348         
5349         if (!module->dynamic_image)
5350                 mono_image_module_basic_init (module);
5351
5352         assembly = module->dynamic_image;
5353         
5354         if (assembly->save) {
5355                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5356                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5357 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5358         {
5359                 char *swapped = g_malloc (2 * mono_string_length (str));
5360                 const char *p = (const char*)mono_string_chars (str);
5361
5362                 swap_with_size (swapped, p, 2, mono_string_length (str));
5363                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5364                 g_free (swapped);
5365         }
5366 #else
5367                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5368 #endif
5369                 mono_image_add_stream_data (&assembly->us, "", 1);
5370         } else {
5371                 idx = assembly->us.index ++;
5372         }
5373
5374         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5375
5376         return MONO_TOKEN_STRING | idx;
5377 }
5378
5379 guint32
5380 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5381 {
5382         MonoClass *klass;
5383         guint32 token = 0;
5384         MonoMethodSignature *sig;
5385
5386         mono_error_init (error);
5387
5388         klass = obj->vtable->klass;
5389         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5390                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5391                 MonoMethodSignature *old;
5392                 guint32 sig_token, parent;
5393                 int nargs, i;
5394
5395                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5396
5397                 nargs = mono_array_length (opt_param_types);
5398                 old = mono_method_signature (method);
5399                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5400
5401                 sig->hasthis = old->hasthis;
5402                 sig->explicit_this = old->explicit_this;
5403                 sig->call_convention = old->call_convention;
5404                 sig->generic_param_count = old->generic_param_count;
5405                 sig->param_count = old->param_count + nargs;
5406                 sig->sentinelpos = old->param_count;
5407                 sig->ret = old->ret;
5408
5409                 for (i = 0; i < old->param_count; i++)
5410                         sig->params [i] = old->params [i];
5411
5412                 for (i = 0; i < nargs; i++) {
5413                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5414                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt, error);
5415                         if (!is_ok (error)) goto fail;
5416                 }
5417
5418                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5419                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5420                 parent >>= MONO_TYPEDEFORREF_BITS;
5421
5422                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5423                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5424
5425                 sig_token = method_encode_signature (assembly, sig);
5426                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5427         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5428                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5429                 ReflectionMethodBuilder rmb;
5430                 guint32 parent, sig_token;
5431                 int nopt_args, nparams, ngparams, i;
5432
5433                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5434                         goto fail;
5435                 
5436                 rmb.opt_types = opt_param_types;
5437                 nopt_args = mono_array_length (opt_param_types);
5438
5439                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5440                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5441                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5442
5443                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5444                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5445                 sig->call_convention = rmb.call_conv;
5446                 sig->generic_param_count = ngparams;
5447                 sig->param_count = nparams + nopt_args;
5448                 sig->sentinelpos = nparams;
5449                 sig->ret = mono_reflection_type_get_handle (rmb.rtype, error);
5450                 if (!is_ok (error)) goto fail;
5451
5452                 for (i = 0; i < nparams; i++) {
5453                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5454                         sig->params [i] = mono_reflection_type_get_handle (rt, error);
5455                         if (!is_ok (error)) goto fail;
5456                 }
5457
5458                 for (i = 0; i < nopt_args; i++) {
5459                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5460                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt, error);
5461                         if (!is_ok (error)) goto fail;
5462                 }
5463
5464                 sig_token = method_builder_encode_signature (assembly, &rmb, error);
5465                 if (!is_ok (error))
5466                         goto fail;
5467
5468                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5469                 if (!mono_error_ok (error))
5470                         goto fail;
5471                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5472
5473                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5474                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5475
5476                 char *name = mono_string_to_utf8 (rmb.name);
5477                 token = mono_image_get_varargs_method_token (
5478                         assembly, parent, name, sig_token);
5479                 g_free (name);
5480         } else {
5481                 g_error ("requested method token for %s\n", klass->name);
5482         }
5483
5484         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5485         register_dyn_token (assembly, token, obj);
5486         return token;
5487 fail:
5488         g_assert (!mono_error_ok (error));
5489         return 0;
5490 }
5491
5492 /*
5493  * mono_image_create_token:
5494  * @assembly: a dynamic assembly
5495  * @obj:
5496  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5497  *
5498  * Get a token to insert in the IL code stream for the given MemberInfo.
5499  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5500  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5501  * entry.
5502  */
5503 guint32
5504 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5505                          gboolean create_open_instance, gboolean register_token,
5506                          MonoError *error)
5507 {
5508         MonoClass *klass;
5509         guint32 token = 0;
5510
5511         mono_error_init (error);
5512
5513         klass = obj->vtable->klass;
5514
5515         /* Check for user defined reflection objects */
5516         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5517         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5518                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5519                 return 0;
5520         }
5521
5522         if (strcmp (klass->name, "MethodBuilder") == 0) {
5523                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5524                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5525
5526                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5527                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5528                 else {
5529                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5530                         if (!mono_error_ok (error))
5531                                 return 0;
5532                 }
5533                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5534         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5535                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5536                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5537
5538                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5539                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5540                 else {
5541                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5542                         if (!mono_error_ok (error))
5543                                 return 0;
5544                 }
5545                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5546         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5547                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5548                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5549                 if (tb->generic_params) {
5550                         token = mono_image_get_generic_field_token (assembly, fb, error);
5551                         return_val_if_nok (error, 0);
5552                 } else {
5553                         if (tb->module->dynamic_image == assembly) {
5554                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5555                         } else {
5556                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5557                         }
5558                 }
5559         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5560                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5561                 if (create_open_instance && tb->generic_params) {
5562                         MonoType *type;
5563                         init_type_builder_generics (obj);
5564                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5565                         return_val_if_nok (error, 0);
5566                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5567                         token = mono_metadata_token_from_dor (token);
5568                 } else if (tb->module->dynamic_image == assembly) {
5569                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5570                 } else {
5571                         MonoType *type;
5572                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5573                         return_val_if_nok (error, 0);
5574                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5575                 }
5576         } else if (strcmp (klass->name, "MonoType") == 0) {
5577                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5578                 return_val_if_nok (error, 0);
5579                 MonoClass *mc = mono_class_from_mono_type (type);
5580                 token = mono_metadata_token_from_dor (
5581                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5582         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5583                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5584                 return_val_if_nok (error, 0);
5585                 token = mono_metadata_token_from_dor (
5586                         mono_image_typedef_or_ref (assembly, type));
5587         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5588                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5589                 return_val_if_nok (error, 0);
5590                 token = mono_metadata_token_from_dor (
5591                         mono_image_typedef_or_ref (assembly, type));
5592         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5593                    strcmp (klass->name, "MonoMethod") == 0 ||
5594                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5595                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5596                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5597                 if (m->method->is_inflated) {
5598                         if (create_open_instance)
5599                                 token = mono_image_get_methodspec_token (assembly, m->method);
5600                         else
5601                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5602                 } else if ((m->method->klass->image == &assembly->image) &&
5603                          !m->method->klass->generic_class) {
5604                         static guint32 method_table_idx = 0xffffff;
5605                         if (m->method->klass->wastypebuilder) {
5606                                 /* we use the same token as the one that was assigned
5607                                  * to the Methodbuilder.
5608                                  * FIXME: do the equivalent for Fields.
5609                                  */
5610                                 token = m->method->token;
5611                         } else {
5612                                 /*
5613                                  * Each token should have a unique index, but the indexes are
5614                                  * assigned by managed code, so we don't know about them. An
5615                                  * easy solution is to count backwards...
5616                                  */
5617                                 method_table_idx --;
5618                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5619                         }
5620                 } else {
5621                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5622                 }
5623                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5624         } else if (strcmp (klass->name, "MonoField") == 0) {
5625                 MonoReflectionField *f = (MonoReflectionField *)obj;
5626                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5627                         static guint32 field_table_idx = 0xffffff;
5628                         field_table_idx --;
5629                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5630                 } else {
5631                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5632                 }
5633                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5634         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5635                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5636                 token = mono_image_get_array_token (assembly, m);
5637         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5638                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5639                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
5640                 return_val_if_nok (error, 0);
5641         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5642                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5643                 return_val_if_nok (error, 0);
5644                 token = mono_metadata_token_from_dor (
5645                         mono_image_typedef_or_ref (assembly, type));
5646         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5647                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5648                 token = mono_image_get_field_on_inst_token (assembly, f, error);
5649                 return_val_if_nok (error, 0);
5650         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5651                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5652                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5653                 if (!mono_error_ok (error))
5654                         return 0;
5655         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5656                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5657                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5658                 if (!mono_error_ok (error))
5659                         return 0;
5660         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5661                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
5662                 return_val_if_nok (error, 0);
5663                 token = mono_metadata_token_from_dor (
5664                                 mono_image_typedef_or_ref (assembly, type));
5665         } else {
5666                 g_error ("requested token for %s\n", klass->name);
5667         }
5668
5669         if (register_token)
5670                 mono_image_register_token (assembly, token, obj);
5671
5672         return token;
5673 }
5674
5675 /*
5676  * mono_image_register_token:
5677  *
5678  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5679  * the Module.ResolveXXXToken () methods to work.
5680  */
5681 void
5682 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5683 {
5684         MonoObject *prev;
5685
5686         dynamic_image_lock (assembly);
5687         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5688         if (prev) {
5689                 /* There could be multiple MethodInfo objects with the same token */
5690                 //g_assert (prev == obj);
5691         } else {
5692                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5693         }
5694         dynamic_image_unlock (assembly);
5695 }
5696
5697 static MonoDynamicImage*
5698 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5699 {
5700         static const guchar entrycode [16] = {0xff, 0x25, 0};
5701         MonoDynamicImage *image;
5702         int i;
5703
5704         const char *version;
5705
5706         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5707                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5708         else
5709                 version = mono_get_runtime_info ()->runtime_version;
5710
5711 #if HAVE_BOEHM_GC
5712         /* The MonoGHashTable's need GC tracking */
5713         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5714 #else
5715         image = g_new0 (MonoDynamicImage, 1);
5716 #endif
5717
5718         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5719         
5720         /*g_print ("created image %p\n", image);*/
5721         /* keep in sync with image.c */
5722         image->image.name = assembly_name;
5723         image->image.assembly_name = image->image.name; /* they may be different */
5724         image->image.module_name = module_name;
5725         image->image.version = g_strdup (version);
5726         image->image.md_version_major = 1;
5727         image->image.md_version_minor = 1;
5728         image->image.dynamic = TRUE;
5729
5730         image->image.references = g_new0 (MonoAssembly*, 1);
5731         image->image.references [0] = NULL;
5732
5733         mono_image_init (&image->image);
5734
5735         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");
5736         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5737         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5738         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5739         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5740         image->handleref = g_hash_table_new (NULL, NULL);
5741         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");
5742         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5743         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");
5744         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");
5745         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5746         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5747         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5748         image->gen_params = g_ptr_array_new ();
5749         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5750
5751         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5752         string_heap_init (&image->sheap);
5753         mono_image_add_stream_data (&image->us, "", 1);
5754         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5755         /* import tables... */
5756         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5757         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5758         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5759         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5760         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5761         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5762         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5763         stream_data_align (&image->code);
5764
5765         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5766
5767         for (i=0; i < MONO_TABLE_NUM; ++i) {
5768                 image->tables [i].next_idx = 1;
5769                 image->tables [i].columns = table_sizes [i];
5770         }
5771
5772         image->image.assembly = (MonoAssembly*)assembly;
5773         image->run = assembly->run;
5774         image->save = assembly->save;
5775         image->pe_kind = 0x1; /* ILOnly */
5776         image->machine = 0x14c; /* I386 */
5777         
5778         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5779
5780         dynamic_images_lock ();
5781
5782         if (!dynamic_images)
5783                 dynamic_images = g_ptr_array_new ();
5784
5785         g_ptr_array_add (dynamic_images, image);
5786
5787         dynamic_images_unlock ();
5788
5789         return image;
5790 }
5791 #endif
5792
5793 static void
5794 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5795 {
5796         g_free (key);
5797 }
5798
5799 static void
5800 release_hashtable (MonoGHashTable **hash)
5801 {
5802         if (*hash) {
5803                 mono_g_hash_table_destroy (*hash);
5804                 *hash = NULL;
5805         }
5806 }
5807
5808 void
5809 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5810 {
5811         release_hashtable (&image->token_fixups);
5812         release_hashtable (&image->handleref_managed);
5813         release_hashtable (&image->tokens);
5814         release_hashtable (&image->remapped_tokens);
5815         release_hashtable (&image->generic_def_objects);
5816         release_hashtable (&image->methodspec);
5817 }
5818
5819 // Free dynamic image pass one: Free resources but not image itself
5820 void
5821 mono_dynamic_image_free (MonoDynamicImage *image)
5822 {
5823         MonoDynamicImage *di = image;
5824         GList *list;
5825         int i;
5826
5827         if (di->methodspec)
5828                 mono_g_hash_table_destroy (di->methodspec);
5829         if (di->typespec)
5830                 g_hash_table_destroy (di->typespec);
5831         if (di->typeref)
5832                 g_hash_table_destroy (di->typeref);
5833         if (di->handleref)
5834                 g_hash_table_destroy (di->handleref);
5835         if (di->handleref_managed)
5836                 mono_g_hash_table_destroy (di->handleref_managed);
5837         if (di->tokens)
5838                 mono_g_hash_table_destroy (di->tokens);
5839         if (di->remapped_tokens)
5840                 mono_g_hash_table_destroy (di->remapped_tokens);
5841         if (di->generic_def_objects)
5842                 mono_g_hash_table_destroy (di->generic_def_objects);
5843         if (di->blob_cache) {
5844                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5845                 g_hash_table_destroy (di->blob_cache);
5846         }
5847         if (di->standalonesig_cache)
5848                 g_hash_table_destroy (di->standalonesig_cache);
5849         for (list = di->array_methods; list; list = list->next) {
5850                 ArrayMethod *am = (ArrayMethod *)list->data;
5851                 g_free (am->sig);
5852                 g_free (am->name);
5853                 g_free (am);
5854         }
5855         g_list_free (di->array_methods);
5856         if (di->gen_params) {
5857                 for (i = 0; i < di->gen_params->len; i++) {
5858                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5859                         mono_gc_deregister_root ((char*) &entry->gparam);
5860                         g_free (entry);
5861                 }
5862                 g_ptr_array_free (di->gen_params, TRUE);
5863         }
5864         if (di->token_fixups)
5865                 mono_g_hash_table_destroy (di->token_fixups);
5866         if (di->method_to_table_idx)
5867                 g_hash_table_destroy (di->method_to_table_idx);
5868         if (di->field_to_table_idx)
5869                 g_hash_table_destroy (di->field_to_table_idx);
5870         if (di->method_aux_hash)
5871                 g_hash_table_destroy (di->method_aux_hash);
5872         if (di->vararg_aux_hash)
5873                 g_hash_table_destroy (di->vararg_aux_hash);
5874         g_free (di->strong_name);
5875         g_free (di->win32_res);
5876         if (di->public_key)
5877                 g_free (di->public_key);
5878
5879         /*g_print ("string heap destroy for image %p\n", di);*/
5880         mono_dynamic_stream_reset (&di->sheap);
5881         mono_dynamic_stream_reset (&di->code);
5882         mono_dynamic_stream_reset (&di->resources);
5883         mono_dynamic_stream_reset (&di->us);
5884         mono_dynamic_stream_reset (&di->blob);
5885         mono_dynamic_stream_reset (&di->tstream);
5886         mono_dynamic_stream_reset (&di->guid);
5887         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5888                 g_free (di->tables [i].values);
5889         }
5890
5891         dynamic_images_lock ();
5892
5893         if (dynamic_images)
5894                 g_ptr_array_remove (dynamic_images, di);
5895
5896         dynamic_images_unlock ();
5897 }
5898
5899 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5900 void
5901 mono_dynamic_image_free_image (MonoDynamicImage *image)
5902 {
5903         /* See create_dynamic_mono_image () */
5904 #if HAVE_BOEHM_GC
5905         /* Allocated using GC_MALLOC */
5906 #else
5907         g_free (image);
5908 #endif
5909 }
5910
5911 #ifndef DISABLE_REFLECTION_EMIT
5912
5913 /*
5914  * mono_image_basic_init:
5915  * @assembly: an assembly builder object
5916  *
5917  * Create the MonoImage that represents the assembly builder and setup some
5918  * of the helper hash table and the basic metadata streams.
5919  */
5920 void
5921 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5922 {
5923         MonoDynamicAssembly *assembly;
5924         MonoDynamicImage *image;
5925         MonoDomain *domain = mono_object_domain (assemblyb);
5926         
5927         if (assemblyb->dynamic_assembly)
5928                 return;
5929
5930 #if HAVE_BOEHM_GC
5931         /* assembly->assembly.image might be GC allocated */
5932         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5933 #else
5934         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5935 #endif
5936
5937         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5938         
5939         assembly->assembly.ref_count = 1;
5940         assembly->assembly.dynamic = TRUE;
5941         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5942         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5943         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5944         if (assemblyb->culture)
5945                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5946         else
5947                 assembly->assembly.aname.culture = g_strdup ("");
5948
5949         if (assemblyb->version) {
5950                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5951                         char **version = g_strsplit (vstr, ".", 4);
5952                         char **parts = version;
5953                         assembly->assembly.aname.major = atoi (*parts++);
5954                         assembly->assembly.aname.minor = atoi (*parts++);
5955                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5956                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5957
5958                         g_strfreev (version);
5959                         g_free (vstr);
5960         } else {
5961                         assembly->assembly.aname.major = 0;
5962                         assembly->assembly.aname.minor = 0;
5963                         assembly->assembly.aname.build = 0;
5964                         assembly->assembly.aname.revision = 0;
5965         }
5966
5967         assembly->run = assemblyb->access != 2;
5968         assembly->save = assemblyb->access != 1;
5969         assembly->domain = domain;
5970
5971         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5972         image->initial_image = TRUE;
5973         assembly->assembly.aname.name = image->image.name;
5974         assembly->assembly.image = &image->image;
5975         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5976                 /* -1 to correct for the trailing NULL byte */
5977                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5978                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5979                 }
5980                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5981         }
5982
5983         mono_domain_assemblies_lock (domain);
5984         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5985         mono_domain_assemblies_unlock (domain);
5986
5987         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5988         
5989         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5990         
5991         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5992 }
5993
5994 #endif /* !DISABLE_REFLECTION_EMIT */
5995
5996 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5997
5998 static int
5999 calc_section_size (MonoDynamicImage *assembly)
6000 {
6001         int nsections = 0;
6002
6003         /* alignment constraints */
6004         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
6005         g_assert ((assembly->code.index % 4) == 0);
6006         assembly->meta_size += 3;
6007         assembly->meta_size &= ~3;
6008         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
6009         g_assert ((assembly->resources.index % 4) == 0);
6010
6011         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
6012         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
6013         nsections++;
6014
6015         if (assembly->win32_res) {
6016                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
6017
6018                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
6019                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
6020                 nsections++;
6021         }
6022
6023         assembly->sections [MONO_SECTION_RELOC].size = 12;
6024         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
6025         nsections++;
6026
6027         return nsections;
6028 }
6029
6030 typedef struct {
6031         guint32 id;
6032         guint32 offset;
6033         GSList *children;
6034         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
6035 } ResTreeNode;
6036
6037 static int
6038 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
6039 {
6040         ResTreeNode *t1 = (ResTreeNode*)a;
6041         ResTreeNode *t2 = (ResTreeNode*)b;
6042
6043         return t1->id - t2->id;
6044 }
6045
6046 /*
6047  * resource_tree_create:
6048  *
6049  *  Organize the resources into a resource tree.
6050  */
6051 static ResTreeNode *
6052 resource_tree_create (MonoArray *win32_resources)
6053 {
6054         ResTreeNode *tree, *res_node, *type_node, *lang_node;
6055         GSList *l;
6056         int i;
6057
6058         tree = g_new0 (ResTreeNode, 1);
6059         
6060         for (i = 0; i < mono_array_length (win32_resources); ++i) {
6061                 MonoReflectionWin32Resource *win32_res =
6062                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
6063
6064                 /* Create node */
6065
6066                 /* FIXME: BUG: this stores managed references in unmanaged memory */
6067                 lang_node = g_new0 (ResTreeNode, 1);
6068                 lang_node->id = win32_res->lang_id;
6069                 lang_node->win32_res = win32_res;
6070
6071                 /* Create type node if neccesary */
6072                 type_node = NULL;
6073                 for (l = tree->children; l; l = l->next)
6074                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
6075                                 type_node = (ResTreeNode*)l->data;
6076                                 break;
6077                         }
6078
6079                 if (!type_node) {
6080                         type_node = g_new0 (ResTreeNode, 1);
6081                         type_node->id = win32_res->res_type;
6082
6083                         /* 
6084                          * The resource types have to be sorted otherwise
6085                          * Windows Explorer can't display the version information.
6086                          */
6087                         tree->children = g_slist_insert_sorted (tree->children, 
6088                                 type_node, resource_tree_compare_by_id);
6089                 }
6090
6091                 /* Create res node if neccesary */
6092                 res_node = NULL;
6093                 for (l = type_node->children; l; l = l->next)
6094                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
6095                                 res_node = (ResTreeNode*)l->data;
6096                                 break;
6097                         }
6098
6099                 if (!res_node) {
6100                         res_node = g_new0 (ResTreeNode, 1);
6101                         res_node->id = win32_res->res_id;
6102                         type_node->children = g_slist_append (type_node->children, res_node);
6103                 }
6104
6105                 res_node->children = g_slist_append (res_node->children, lang_node);
6106         }
6107
6108         return tree;
6109 }
6110
6111 /*
6112  * resource_tree_encode:
6113  * 
6114  *   Encode the resource tree into the format used in the PE file.
6115  */
6116 static void
6117 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
6118 {
6119         char *entries;
6120         MonoPEResourceDir dir;
6121         MonoPEResourceDirEntry dir_entry;
6122         MonoPEResourceDataEntry data_entry;
6123         GSList *l;
6124         guint32 res_id_entries;
6125
6126         /*
6127          * For the format of the resource directory, see the article
6128          * "An In-Depth Look into the Win32 Portable Executable File Format" by
6129          * Matt Pietrek
6130          */
6131
6132         memset (&dir, 0, sizeof (dir));
6133         memset (&dir_entry, 0, sizeof (dir_entry));
6134         memset (&data_entry, 0, sizeof (data_entry));
6135
6136         g_assert (sizeof (dir) == 16);
6137         g_assert (sizeof (dir_entry) == 8);
6138         g_assert (sizeof (data_entry) == 16);
6139
6140         node->offset = p - begin;
6141
6142         /* IMAGE_RESOURCE_DIRECTORY */
6143         res_id_entries = g_slist_length (node->children);
6144         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
6145
6146         memcpy (p, &dir, sizeof (dir));
6147         p += sizeof (dir);
6148
6149         /* Reserve space for entries */
6150         entries = p;
6151         p += sizeof (dir_entry) * res_id_entries;
6152
6153         /* Write children */
6154         for (l = node->children; l; l = l->next) {
6155                 ResTreeNode *child = (ResTreeNode*)l->data;
6156
6157                 if (child->win32_res) {
6158                         guint32 size;
6159
6160                         child->offset = p - begin;
6161
6162                         /* IMAGE_RESOURCE_DATA_ENTRY */
6163                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
6164                         size = mono_array_length (child->win32_res->res_data);
6165                         data_entry.rde_size = GUINT32_TO_LE (size);
6166
6167                         memcpy (p, &data_entry, sizeof (data_entry));
6168                         p += sizeof (data_entry);
6169
6170                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
6171                         p += size;
6172                 } else {
6173                         resource_tree_encode (child, begin, p, &p);
6174                 }
6175         }
6176
6177         /* IMAGE_RESOURCE_ENTRY */
6178         for (l = node->children; l; l = l->next) {
6179                 ResTreeNode *child = (ResTreeNode*)l->data;
6180
6181                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
6182                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
6183
6184                 memcpy (entries, &dir_entry, sizeof (dir_entry));
6185                 entries += sizeof (dir_entry);
6186         }
6187
6188         *endbuf = p;
6189 }
6190
6191 static void
6192 resource_tree_free (ResTreeNode * node)
6193 {
6194         GSList * list;
6195         for (list = node->children; list; list = list->next)
6196                 resource_tree_free ((ResTreeNode*)list->data);
6197         g_slist_free(node->children);
6198         g_free (node);
6199 }
6200
6201 static void
6202 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
6203 {
6204         char *buf;
6205         char *p;
6206         guint32 size, i;
6207         MonoReflectionWin32Resource *win32_res;
6208         ResTreeNode *tree;
6209
6210         if (!assemblyb->win32_resources)
6211                 return;
6212
6213         /*
6214          * Resources are stored in a three level tree inside the PE file.
6215          * - level one contains a node for each type of resource
6216          * - level two contains a node for each resource
6217          * - level three contains a node for each instance of a resource for a
6218          *   specific language.
6219          */
6220
6221         tree = resource_tree_create (assemblyb->win32_resources);
6222
6223         /* Estimate the size of the encoded tree */
6224         size = 0;
6225         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6226                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6227                 size += mono_array_length (win32_res->res_data);
6228         }
6229         /* Directory structure */
6230         size += mono_array_length (assemblyb->win32_resources) * 256;
6231         p = buf = (char *)g_malloc (size);
6232
6233         resource_tree_encode (tree, p, p, &p);
6234
6235         g_assert (p - buf <= size);
6236
6237         assembly->win32_res = (char *)g_malloc (p - buf);
6238         assembly->win32_res_size = p - buf;
6239         memcpy (assembly->win32_res, buf, p - buf);
6240
6241         g_free (buf);
6242         resource_tree_free (tree);
6243 }
6244
6245 static void
6246 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6247 {
6248         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6249         int i;
6250
6251         p += sizeof (MonoPEResourceDir);
6252         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6253                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6254                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6255                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6256                         fixup_resource_directory (res_section, child, rva);
6257                 } else {
6258                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6259                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6260                 }
6261
6262                 p += sizeof (MonoPEResourceDirEntry);
6263         }
6264 }
6265
6266 static void
6267 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6268 {
6269         guint32 dummy;
6270         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6271                 g_error ("WriteFile returned %d\n", GetLastError ());
6272 }
6273
6274 /*
6275  * mono_image_create_pefile:
6276  * @mb: a module builder object
6277  * 
6278  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6279  * assembly->pefile where it can be easily retrieved later in chunks.
6280  */
6281 gboolean
6282 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6283 {
6284         MonoMSDOSHeader *msdos;
6285         MonoDotNetHeader *header;
6286         MonoSectionTable *section;
6287         MonoCLIHeader *cli_header;
6288         guint32 size, image_size, virtual_base, text_offset;
6289         guint32 header_start, section_start, file_offset, virtual_offset;
6290         MonoDynamicImage *assembly;
6291         MonoReflectionAssemblyBuilder *assemblyb;
6292         MonoDynamicStream pefile_stream = {0};
6293         MonoDynamicStream *pefile = &pefile_stream;
6294         int i, nsections;
6295         guint32 *rva, value;
6296         guchar *p;
6297         static const unsigned char msheader[] = {
6298                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6299                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6300                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6301                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6302                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6303                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6304                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6305                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6306         };
6307
6308         mono_error_init (error);
6309
6310         assemblyb = mb->assemblyb;
6311
6312         mono_image_basic_init (assemblyb);
6313         assembly = mb->dynamic_image;
6314
6315         assembly->pe_kind = assemblyb->pe_kind;
6316         assembly->machine = assemblyb->machine;
6317         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6318         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6319         
6320         if (!mono_image_build_metadata (mb, error))
6321                 return FALSE;
6322         
6323
6324         if (mb->is_main && assemblyb->resources) {
6325                 int len = mono_array_length (assemblyb->resources);
6326                 for (i = 0; i < len; ++i)
6327                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6328         }
6329
6330         if (mb->resources) {
6331                 int len = mono_array_length (mb->resources);
6332                 for (i = 0; i < len; ++i)
6333                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6334         }
6335
6336         if (!build_compressed_metadata (assembly, error))
6337                 return FALSE;
6338
6339         if (mb->is_main)
6340                 assembly_add_win32_resources (assembly, assemblyb);
6341
6342         nsections = calc_section_size (assembly);
6343         
6344         /* The DOS header and stub */
6345         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6346         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6347
6348         /* the dotnet header */
6349         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6350
6351         /* the section tables */
6352         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6353
6354         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6355         virtual_offset = VIRT_ALIGN;
6356         image_size = 0;
6357
6358         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6359                 if (!assembly->sections [i].size)
6360                         continue;
6361                 /* align offsets */
6362                 file_offset += FILE_ALIGN - 1;
6363                 file_offset &= ~(FILE_ALIGN - 1);
6364                 virtual_offset += VIRT_ALIGN - 1;
6365                 virtual_offset &= ~(VIRT_ALIGN - 1);
6366
6367                 assembly->sections [i].offset = file_offset;
6368                 assembly->sections [i].rva = virtual_offset;
6369
6370                 file_offset += assembly->sections [i].size;
6371                 virtual_offset += assembly->sections [i].size;
6372                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6373         }
6374
6375         file_offset += FILE_ALIGN - 1;
6376         file_offset &= ~(FILE_ALIGN - 1);
6377
6378         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6379
6380         /* back-patch info */
6381         msdos = (MonoMSDOSHeader*)pefile->data;
6382         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6383
6384         header = (MonoDotNetHeader*)(pefile->data + header_start);
6385         header->pesig [0] = 'P';
6386         header->pesig [1] = 'E';
6387         
6388         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6389         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6390         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6391         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6392         if (assemblyb->pekind == 1) {
6393                 /* it's a dll */
6394                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6395         } else {
6396                 /* it's an exe */
6397                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6398         }
6399
6400         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6401
6402         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6403         header->pe.pe_major = 6;
6404         header->pe.pe_minor = 0;
6405         size = assembly->sections [MONO_SECTION_TEXT].size;
6406         size += FILE_ALIGN - 1;
6407         size &= ~(FILE_ALIGN - 1);
6408         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6409         size = assembly->sections [MONO_SECTION_RSRC].size;
6410         size += FILE_ALIGN - 1;
6411         size &= ~(FILE_ALIGN - 1);
6412         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6413         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6414         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6415         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6416         /* pe_rva_entry_point always at the beginning of the text section */
6417         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6418
6419         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6420         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6421         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6422         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6423         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6424         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6425         size = section_start;
6426         size += FILE_ALIGN - 1;
6427         size &= ~(FILE_ALIGN - 1);
6428         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6429         size = image_size;
6430         size += VIRT_ALIGN - 1;
6431         size &= ~(VIRT_ALIGN - 1);
6432         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6433
6434         /*
6435         // Translate the PEFileKind value to the value expected by the Windows loader
6436         */
6437         {
6438                 short kind;
6439
6440                 /*
6441                 // PEFileKinds.Dll == 1
6442                 // PEFileKinds.ConsoleApplication == 2
6443                 // PEFileKinds.WindowApplication == 3
6444                 //
6445                 // need to get:
6446                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6447                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6448                 */
6449                 if (assemblyb->pekind == 3)
6450                         kind = 2;
6451                 else
6452                         kind = 3;
6453                 
6454                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6455         }    
6456         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6457         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6458         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6459         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6460         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6461         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6462
6463         /* fill data directory entries */
6464
6465         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6466         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6467
6468         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6469         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6470
6471         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6472         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6473         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6474         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6475         /* patch entrypoint name */
6476         if (assemblyb->pekind == 1)
6477                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6478         else
6479                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6480         /* patch imported function RVA name */
6481         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6482         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6483
6484         /* the import table */
6485         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6486         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6487         /* patch imported dll RVA name and other entries in the dir */
6488         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6489         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6490         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6491         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6492         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6493         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6494
6495         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6496         value = (assembly->text_rva + assembly->imp_names_offset);
6497         *p++ = (value) & 0xff;
6498         *p++ = (value >> 8) & (0xff);
6499         *p++ = (value >> 16) & (0xff);
6500         *p++ = (value >> 24) & (0xff);
6501
6502         /* the CLI header info */
6503         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6504         cli_header->ch_size = GUINT32_FROM_LE (72);
6505         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6506         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6507         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6508         if (assemblyb->entry_point) {
6509                 guint32 table_idx = 0;
6510                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6511                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6512                         table_idx = methodb->table_idx;
6513                 } else {
6514                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6515                 }
6516                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6517         } else {
6518                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6519         }
6520         /* The embedded managed resources */
6521         text_offset = assembly->text_rva + assembly->code.index;
6522         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6523         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6524         text_offset += assembly->resources.index;
6525         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6526         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6527         text_offset += assembly->meta_size;
6528         if (assembly->strong_name_size) {
6529                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6530                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6531                 text_offset += assembly->strong_name_size;
6532         }
6533
6534         /* write the section tables and section content */
6535         section = (MonoSectionTable*)(pefile->data + section_start);
6536         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6537                 static const char section_names [][7] = {
6538                         ".text", ".rsrc", ".reloc"
6539                 };
6540                 if (!assembly->sections [i].size)
6541                         continue;
6542                 strcpy (section->st_name, section_names [i]);
6543                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6544                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6545                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6546                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6547                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6548                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6549                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6550                 section ++;
6551         }
6552         
6553         checked_write_file (file, pefile->data, pefile->index);
6554         
6555         mono_dynamic_stream_reset (pefile);
6556         
6557         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6558                 if (!assembly->sections [i].size)
6559                         continue;
6560                 
6561                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6562                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6563                 
6564                 switch (i) {
6565                 case MONO_SECTION_TEXT:
6566                         /* patch entry point */
6567                         p = (guchar*)(assembly->code.data + 2);
6568                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6569                         *p++ = (value) & 0xff;
6570                         *p++ = (value >> 8) & 0xff;
6571                         *p++ = (value >> 16) & 0xff;
6572                         *p++ = (value >> 24) & 0xff;
6573                 
6574                         checked_write_file (file, assembly->code.data, assembly->code.index);
6575                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6576                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6577                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6578                                 
6579
6580                         g_free (assembly->image.raw_metadata);
6581                         break;
6582                 case MONO_SECTION_RELOC: {
6583                         struct {
6584                                 guint32 page_rva;
6585                                 guint32 block_size;
6586                                 guint16 type_and_offset;
6587                                 guint16 term;
6588                         } reloc;
6589                         
6590                         g_assert (sizeof (reloc) == 12);
6591                         
6592                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6593                         reloc.block_size = GUINT32_FROM_LE (12);
6594                         
6595                         /* 
6596                          * the entrypoint is always at the start of the text section 
6597                          * 3 is IMAGE_REL_BASED_HIGHLOW
6598                          * 2 is patch_size_rva - text_rva
6599                          */
6600                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6601                         reloc.term = 0;
6602                         
6603                         checked_write_file (file, &reloc, sizeof (reloc));
6604                         
6605                         break;
6606                 }
6607                 case MONO_SECTION_RSRC:
6608                         if (assembly->win32_res) {
6609
6610                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6611                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6612                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6613                         }
6614                         break;
6615                 default:
6616                         g_assert_not_reached ();
6617                 }
6618         }
6619         
6620         /* check that the file is properly padded */
6621         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6622                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6623         if (! SetEndOfFile (file))
6624                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6625         
6626         mono_dynamic_stream_reset (&assembly->code);
6627         mono_dynamic_stream_reset (&assembly->us);
6628         mono_dynamic_stream_reset (&assembly->blob);
6629         mono_dynamic_stream_reset (&assembly->guid);
6630         mono_dynamic_stream_reset (&assembly->sheap);
6631
6632         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6633         g_hash_table_destroy (assembly->blob_cache);
6634         assembly->blob_cache = NULL;
6635
6636         return TRUE;
6637 }
6638
6639 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6640
6641 gboolean
6642 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6643 {
6644         g_assert_not_reached ();
6645 }
6646
6647 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6648
6649 #ifndef DISABLE_REFLECTION_EMIT
6650
6651 MonoReflectionModule *
6652 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6653 {
6654         MonoError error;
6655         MonoReflectionModule *result = NULL;
6656         char *name;
6657         MonoImage *image;
6658         MonoImageOpenStatus status;
6659         MonoDynamicAssembly *assembly;
6660         guint32 module_count;
6661         MonoImage **new_modules;
6662         gboolean *new_modules_loaded;
6663         
6664         name = mono_string_to_utf8 (fileName);
6665
6666         image = mono_image_open (name, &status);
6667         if (!image) {
6668                 MonoException *exc;
6669                 if (status == MONO_IMAGE_ERROR_ERRNO)
6670                         exc = mono_get_exception_file_not_found (fileName);
6671                 else
6672                         exc = mono_get_exception_bad_image_format (name);
6673                 g_free (name);
6674                 mono_raise_exception (exc);
6675         }
6676
6677         g_free (name);
6678
6679         assembly = ab->dynamic_assembly;
6680         image->assembly = (MonoAssembly*)assembly;
6681
6682         module_count = image->assembly->image->module_count;
6683         new_modules = g_new0 (MonoImage *, module_count + 1);
6684         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6685
6686         if (image->assembly->image->modules)
6687                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6688         if (image->assembly->image->modules_loaded)
6689                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6690         new_modules [module_count] = image;
6691         new_modules_loaded [module_count] = TRUE;
6692         mono_image_addref (image);
6693
6694         g_free (image->assembly->image->modules);
6695         image->assembly->image->modules = new_modules;
6696         image->assembly->image->modules_loaded = new_modules_loaded;
6697         image->assembly->image->module_count ++;
6698
6699         mono_assembly_load_references (image, &status);
6700         if (status) {
6701                 mono_image_close (image);
6702                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6703         }
6704
6705         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6706         mono_error_raise_exception (&error); /* FIXME don't raise here */
6707         return result;
6708 }
6709
6710 #endif /* DISABLE_REFLECTION_EMIT */
6711
6712 /*
6713  * We need to return always the same object for MethodInfo, FieldInfo etc..
6714  * but we need to consider the reflected type.
6715  * type uses a different hash, since it uses custom hash/equal functions.
6716  */
6717
6718 typedef struct {
6719         gpointer item;
6720         MonoClass *refclass;
6721 } ReflectedEntry;
6722
6723 static gboolean
6724 reflected_equal (gconstpointer a, gconstpointer b) {
6725         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6726         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6727
6728         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6729 }
6730
6731 static guint
6732 reflected_hash (gconstpointer a) {
6733         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6734         return mono_aligned_addr_hash (ea->item);
6735 }
6736
6737 #define CHECK_OBJECT(t,p,k)     \
6738         do {    \
6739                 t _obj; \
6740                 ReflectedEntry e;       \
6741                 e.item = (p);   \
6742                 e.refclass = (k);       \
6743                 mono_domain_lock (domain);      \
6744                 if (!domain->refobject_hash)    \
6745                         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");  \
6746                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6747                         mono_domain_unlock (domain);    \
6748                         return _obj;    \
6749                 }       \
6750         mono_domain_unlock (domain); \
6751         } while (0)
6752
6753 #ifdef HAVE_BOEHM_GC
6754 /* ReflectedEntry doesn't need to be GC tracked */
6755 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6756 #define FREE_REFENTRY(entry) g_free ((entry))
6757 #define REFENTRY_REQUIRES_CLEANUP
6758 #else
6759 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6760 /* FIXME: */
6761 #define FREE_REFENTRY(entry)
6762 #endif
6763
6764 #define CACHE_OBJECT(t,p,o,k)   \
6765         do {    \
6766                 t _obj; \
6767         ReflectedEntry pe; \
6768         pe.item = (p); \
6769         pe.refclass = (k); \
6770         mono_domain_lock (domain); \
6771                 if (!domain->refobject_hash)    \
6772                         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");  \
6773         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6774         if (!_obj) { \
6775                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6776                     e->item = (p);      \
6777                     e->refclass = (k);  \
6778                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6779             _obj = o; \
6780         } \
6781                 mono_domain_unlock (domain);    \
6782         return _obj; \
6783         } while (0)
6784
6785 static void
6786 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6787 {
6788         mono_domain_lock (domain);
6789         if (domain->refobject_hash) {
6790         ReflectedEntry pe;
6791                 gpointer orig_pe, orig_value;
6792
6793                 pe.item = o;
6794                 pe.refclass = klass;
6795                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6796                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6797                         FREE_REFENTRY (orig_pe);
6798                 }
6799         }
6800         mono_domain_unlock (domain);
6801 }
6802
6803 #ifdef REFENTRY_REQUIRES_CLEANUP
6804 static void
6805 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6806 {
6807         FREE_REFENTRY (key);
6808 }
6809 #endif
6810
6811 void
6812 mono_reflection_cleanup_domain (MonoDomain *domain)
6813 {
6814         if (domain->refobject_hash) {
6815 /*let's avoid scanning the whole hashtable if not needed*/
6816 #ifdef REFENTRY_REQUIRES_CLEANUP
6817                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6818 #endif
6819                 mono_g_hash_table_destroy (domain->refobject_hash);
6820                 domain->refobject_hash = NULL;
6821         }
6822 }
6823
6824 #ifndef DISABLE_REFLECTION_EMIT
6825 static gpointer
6826 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6827 {
6828         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6829 }
6830
6831 static gpointer
6832 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6833 {
6834         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6835 }
6836
6837 void
6838 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6839 {
6840         MonoDynamicImage *image = moduleb->dynamic_image;
6841         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6842         if (!image) {
6843                 MonoError error;
6844                 int module_count;
6845                 MonoImage **new_modules;
6846                 MonoImage *ass;
6847                 char *name, *fqname;
6848                 /*
6849                  * FIXME: we already created an image in mono_image_basic_init (), but
6850                  * we don't know which module it belongs to, since that is only 
6851                  * determined at assembly save time.
6852                  */
6853                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6854                 name = mono_string_to_utf8 (ab->name);
6855                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6856                 if (!mono_error_ok (&error)) {
6857                         g_free (name);
6858                         mono_error_raise_exception (&error);
6859                 }
6860                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6861
6862                 moduleb->module.image = &image->image;
6863                 moduleb->dynamic_image = image;
6864                 register_module (mono_object_domain (moduleb), moduleb, image);
6865
6866                 /* register the module with the assembly */
6867                 ass = ab->dynamic_assembly->assembly.image;
6868                 module_count = ass->module_count;
6869                 new_modules = g_new0 (MonoImage *, module_count + 1);
6870
6871                 if (ass->modules)
6872                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6873                 new_modules [module_count] = &image->image;
6874                 mono_image_addref (&image->image);
6875
6876                 g_free (ass->modules);
6877                 ass->modules = new_modules;
6878                 ass->module_count ++;
6879         }
6880 }
6881
6882 void
6883 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6884 {
6885         MonoDynamicImage *image = moduleb->dynamic_image;
6886
6887         g_assert (type->type);
6888         image->wrappers_type = mono_class_from_mono_type (type->type);
6889 }
6890
6891 #endif
6892
6893 /*
6894  * mono_assembly_get_object:
6895  * @domain: an app domain
6896  * @assembly: an assembly
6897  *
6898  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6899  */
6900 MonoReflectionAssembly*
6901 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6902 {
6903         MonoError error;
6904         MonoReflectionAssembly *result;
6905         result = mono_assembly_get_object_checked (domain, assembly, &error);
6906         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6907         return result;
6908 }
6909 /*
6910  * mono_assembly_get_object_checked:
6911  * @domain: an app domain
6912  * @assembly: an assembly
6913  *
6914  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6915  */
6916 MonoReflectionAssembly*
6917 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6918 {
6919         MonoReflectionAssembly *res;
6920         
6921         mono_error_init (error);
6922
6923         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6924         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6925         if (!res)
6926                 return NULL;
6927         res->assembly = assembly;
6928
6929         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6930 }
6931
6932
6933
6934 MonoReflectionModule*   
6935 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6936 {
6937         MonoError error;
6938         MonoReflectionModule *result;
6939         result = mono_module_get_object_checked (domain, image, &error);
6940         mono_error_raise_exception (&error);
6941         return result;
6942 }
6943
6944 MonoReflectionModule*
6945 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6946 {
6947         MonoReflectionModule *res;
6948         char* basename;
6949         
6950         mono_error_init (error);
6951         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6952         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6953         if (!res)
6954                 return NULL;
6955
6956         res->image = image;
6957         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6958         if (!assm_obj)
6959                 return NULL;
6960         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6961
6962         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6963         basename = g_path_get_basename (image->name);
6964         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6965         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6966         
6967         g_free (basename);
6968
6969         if (image->assembly->image == image) {
6970                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6971         } else {
6972                 int i;
6973                 res->token = 0;
6974                 if (image->assembly->image->modules) {
6975                         for (i = 0; i < image->assembly->image->module_count; i++) {
6976                                 if (image->assembly->image->modules [i] == image)
6977                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6978                         }
6979                         g_assert (res->token);
6980                 }
6981         }
6982
6983         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6984 }
6985
6986 MonoReflectionModule*
6987 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6988 {
6989         MonoError error;
6990         MonoReflectionModule *result;
6991         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6992         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6993         return result;
6994 }
6995
6996 MonoReflectionModule*
6997 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6998 {
6999         MonoReflectionModule *res;
7000         MonoTableInfo *table;
7001         guint32 cols [MONO_FILE_SIZE];
7002         const char *name;
7003         guint32 i, name_idx;
7004         const char *val;
7005         
7006         mono_error_init (error);
7007
7008         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
7009         if (!res)
7010                 return NULL;
7011
7012         table = &image->tables [MONO_TABLE_FILE];
7013         g_assert (table_index < table->rows);
7014         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
7015
7016         res->image = NULL;
7017         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
7018         if (!assm_obj)
7019                 return NULL;
7020         MONO_OBJECT_SETREF (res, assembly, assm_obj);
7021         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
7022
7023         /* Check whenever the row has a corresponding row in the moduleref table */
7024         table = &image->tables [MONO_TABLE_MODULEREF];
7025         for (i = 0; i < table->rows; ++i) {
7026                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
7027                 val = mono_metadata_string_heap (image, name_idx);
7028                 if (strcmp (val, name) == 0)
7029                         res->image = image->modules [i];
7030         }
7031
7032         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
7033         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
7034         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
7035         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
7036         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
7037
7038         return res;
7039 }
7040
7041 static gboolean
7042 verify_safe_for_managed_space (MonoType *type)
7043 {
7044         switch (type->type) {
7045 #ifdef DEBUG_HARDER
7046         case MONO_TYPE_ARRAY:
7047                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
7048         case MONO_TYPE_PTR:
7049                 return verify_safe_for_managed_space (type->data.type);
7050         case MONO_TYPE_SZARRAY:
7051                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
7052         case MONO_TYPE_GENERICINST: {
7053                 MonoGenericInst *inst = type->data.generic_class->inst;
7054                 int i;
7055                 if (!inst->is_open)
7056                         break;
7057                 for (i = 0; i < inst->type_argc; ++i)
7058                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
7059                                 return FALSE;
7060                 return TRUE;
7061         }
7062 #endif
7063         case MONO_TYPE_VAR:
7064         case MONO_TYPE_MVAR:
7065                 return TRUE;
7066         default:
7067                 return TRUE;
7068         }
7069 }
7070
7071 static MonoType*
7072 mono_type_normalize (MonoType *type)
7073 {
7074         int i;
7075         MonoGenericClass *gclass;
7076         MonoGenericInst *ginst;
7077         MonoClass *gtd;
7078         MonoGenericContainer *gcontainer;
7079         MonoType **argv = NULL;
7080         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
7081
7082         if (type->type != MONO_TYPE_GENERICINST)
7083                 return type;
7084
7085         gclass = type->data.generic_class;
7086         ginst = gclass->context.class_inst;
7087         if (!ginst->is_open)
7088                 return type;
7089
7090         gtd = gclass->container_class;
7091         gcontainer = gtd->generic_container;
7092         argv = g_newa (MonoType*, ginst->type_argc);
7093
7094         for (i = 0; i < ginst->type_argc; ++i) {
7095                 MonoType *t = ginst->type_argv [i], *norm;
7096                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
7097                         is_denorm_gtd = FALSE;
7098                 norm = mono_type_normalize (t);
7099                 argv [i] = norm;
7100                 if (norm != t)
7101                         requires_rebind = TRUE;
7102         }
7103
7104         if (is_denorm_gtd)
7105                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
7106
7107         if (requires_rebind) {
7108                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
7109                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
7110         }
7111
7112         return type;
7113 }
7114 /*
7115  * mono_type_get_object:
7116  * @domain: an app domain
7117  * @type: a type
7118  *
7119  * Return an System.MonoType object representing the type @type.
7120  */
7121 MonoReflectionType*
7122 mono_type_get_object (MonoDomain *domain, MonoType *type)
7123 {
7124         MonoError error;
7125         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
7126         mono_error_raise_exception (&error);
7127
7128         return ret;
7129 }
7130
7131 MonoReflectionType*
7132 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
7133 {
7134         MonoType *norm_type;
7135         MonoReflectionType *res;
7136         MonoClass *klass;
7137
7138         mono_error_init (error);
7139
7140         klass = mono_class_from_mono_type (type);
7141
7142         /*we must avoid using @type as it might have come
7143          * from a mono_metadata_type_dup and the caller
7144          * expects that is can be freed.
7145          * Using the right type from 
7146          */
7147         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
7148
7149         /* void is very common */
7150         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
7151                 return (MonoReflectionType*)domain->typeof_void;
7152
7153         /*
7154          * If the vtable of the given class was already created, we can use
7155          * the MonoType from there and avoid all locking and hash table lookups.
7156          * 
7157          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
7158          * that the resulting object is different.   
7159          */
7160         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
7161                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
7162                 if (vtable && vtable->type)
7163                         return (MonoReflectionType *)vtable->type;
7164         }
7165
7166         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
7167         mono_domain_lock (domain);
7168         if (!domain->type_hash)
7169                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
7170                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
7171         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
7172                 mono_domain_unlock (domain);
7173                 mono_loader_unlock ();
7174                 return res;
7175         }
7176
7177         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
7178          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
7179          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
7180          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
7181          * artifact of how generics are encoded and should be transparent to managed code so we
7182          * need to weed out this diference when retrieving managed System.Type objects.
7183          */
7184         norm_type = mono_type_normalize (type);
7185         if (norm_type != type) {
7186                 res = mono_type_get_object_checked (domain, norm_type, error);
7187                 if (!mono_error_ok (error))
7188                         return NULL;
7189                 mono_g_hash_table_insert (domain->type_hash, type, res);
7190                 mono_domain_unlock (domain);
7191                 mono_loader_unlock ();
7192                 return res;
7193         }
7194
7195         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
7196         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
7197                 g_assert (0);
7198
7199         if (!verify_safe_for_managed_space (type)) {
7200                 mono_domain_unlock (domain);
7201                 mono_loader_unlock ();
7202                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
7203                 return NULL;
7204         }
7205
7206         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
7207                 gboolean is_type_done = TRUE;
7208                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
7209                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
7210                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
7211                 */
7212                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
7213                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
7214
7215                         if (gparam->owner && gparam->owner->is_method) {
7216                                 MonoMethod *method = gparam->owner->owner.method;
7217                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7218                                         is_type_done = FALSE;
7219                         } else if (gparam->owner && !gparam->owner->is_method) {
7220                                 MonoClass *klass = gparam->owner->owner.klass;
7221                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7222                                         is_type_done = FALSE;
7223                         }
7224                 } 
7225
7226                 /* g_assert_not_reached (); */
7227                 /* should this be considered an error condition? */
7228                 if (is_type_done && !type->byref) {
7229                         mono_domain_unlock (domain);
7230                         mono_loader_unlock ();
7231                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7232                 }
7233         }
7234         /* This is stored in vtables/JITted code so it has to be pinned */
7235         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7236         if (!mono_error_ok (error))
7237                 return NULL;
7238
7239         res->type = type;
7240         mono_g_hash_table_insert (domain->type_hash, type, res);
7241
7242         if (type->type == MONO_TYPE_VOID)
7243                 domain->typeof_void = (MonoObject*)res;
7244
7245         mono_domain_unlock (domain);
7246         mono_loader_unlock ();
7247         return res;
7248 }
7249
7250 /*
7251  * mono_method_get_object:
7252  * @domain: an app domain
7253  * @method: a method
7254  * @refclass: the reflected type (can be NULL)
7255  *
7256  * Return an System.Reflection.MonoMethod object representing the method @method.
7257  */
7258 MonoReflectionMethod*
7259 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7260 {
7261         MonoError error;
7262         MonoReflectionMethod *ret = NULL;
7263         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7264         mono_error_raise_exception (&error);
7265         return ret;
7266 }
7267
7268 /*
7269  * mono_method_get_object_checked:
7270  * @domain: an app domain
7271  * @method: a method
7272  * @refclass: the reflected type (can be NULL)
7273  * @error: set on error.
7274  *
7275  * Return an System.Reflection.MonoMethod object representing the method @method.
7276  * Returns NULL and sets @error on error.
7277  */
7278 MonoReflectionMethod*
7279 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7280 {
7281         /*
7282          * We use the same C representation for methods and constructors, but the type 
7283          * name in C# is different.
7284          */
7285         MonoReflectionType *rt;
7286         MonoClass *klass;
7287         MonoReflectionMethod *ret;
7288
7289         mono_error_init (error);
7290
7291         if (method->is_inflated) {
7292                 MonoReflectionGenericMethod *gret;
7293
7294                 if (!refclass)
7295                         refclass = method->klass;
7296                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7297                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7298                         klass = mono_class_get_mono_generic_cmethod_class ();
7299                 } else {
7300                         klass = mono_class_get_mono_generic_method_class ();
7301                 }
7302                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7303                 if (!mono_error_ok (error))
7304                         goto leave;
7305                 gret->method.method = method;
7306
7307                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7308
7309                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7310                 if (!mono_error_ok (error))
7311                     goto leave;
7312
7313                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7314
7315                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7316         }
7317
7318         if (!refclass)
7319                 refclass = method->klass;
7320
7321         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7322         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7323                 klass = mono_class_get_mono_cmethod_class ();
7324         }
7325         else {
7326                 klass = mono_class_get_mono_method_class ();
7327         }
7328         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7329         if (!mono_error_ok (error))
7330                 goto leave;
7331         ret->method = method;
7332
7333         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7334         if (!mono_error_ok (error))
7335                 goto leave;
7336
7337         MONO_OBJECT_SETREF (ret, reftype, rt);
7338
7339         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7340
7341 leave:
7342         g_assert (!mono_error_ok (error));
7343         return NULL;
7344 }
7345
7346 /*
7347  * mono_method_clear_object:
7348  *
7349  *   Clear the cached reflection objects for the dynamic method METHOD.
7350  */
7351 void
7352 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7353 {
7354         MonoClass *klass;
7355         g_assert (method_is_dynamic (method));
7356
7357         klass = method->klass;
7358         while (klass) {
7359                 clear_cached_object (domain, method, klass);
7360                 klass = klass->parent;
7361         }
7362         /* Added by mono_param_get_objects () */
7363         clear_cached_object (domain, &(method->signature), NULL);
7364         klass = method->klass;
7365         while (klass) {
7366                 clear_cached_object (domain, &(method->signature), klass);
7367                 klass = klass->parent;
7368         }
7369 }
7370
7371 /*
7372  * mono_field_get_object:
7373  * @domain: an app domain
7374  * @klass: a type
7375  * @field: a field
7376  *
7377  * Return an System.Reflection.MonoField object representing the field @field
7378  * in class @klass.
7379  */
7380 MonoReflectionField*
7381 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7382 {
7383         MonoError error;
7384         MonoReflectionField *result;
7385         result = mono_field_get_object_checked (domain, klass, field, &error);
7386         mono_error_raise_exception (&error);
7387         return result;
7388 }
7389
7390 /*
7391  * mono_field_get_object_checked:
7392  * @domain: an app domain
7393  * @klass: a type
7394  * @field: a field
7395  * @error: set on error
7396  *
7397  * Return an System.Reflection.MonoField object representing the field @field
7398  * in class @klass. On error, returns NULL and sets @error.
7399  */
7400 MonoReflectionField*
7401 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7402 {
7403         MonoReflectionType *rt;
7404         MonoReflectionField *res;
7405
7406         mono_error_init (error);
7407
7408         CHECK_OBJECT (MonoReflectionField *, field, klass);
7409         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7410         if (!res)
7411                 return NULL;
7412         res->klass = klass;
7413         res->field = field;
7414         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7415
7416         if (is_field_on_inst (field)) {
7417                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7418
7419                 rt = mono_type_get_object_checked (domain, field->type, error);
7420                 if (!mono_error_ok (error))
7421                         return NULL;
7422
7423                 MONO_OBJECT_SETREF (res, type, rt);
7424         } else {
7425                 if (field->type) {
7426                         rt = mono_type_get_object_checked (domain, field->type, error);
7427                         if (!mono_error_ok (error))
7428                                 return NULL;
7429
7430                         MONO_OBJECT_SETREF (res, type, rt);
7431                 }
7432                 res->attrs = mono_field_get_flags (field);
7433         }
7434         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7435 }
7436
7437 /*
7438  * mono_property_get_object:
7439  * @domain: an app domain
7440  * @klass: a type
7441  * @property: a property
7442  *
7443  * Return an System.Reflection.MonoProperty object representing the property @property
7444  * in class @klass.
7445  */
7446 MonoReflectionProperty*
7447 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7448 {
7449         MonoError error;
7450         MonoReflectionProperty *result;
7451         result = mono_property_get_object_checked (domain, klass, property, &error);
7452         mono_error_raise_exception (&error);
7453         return result;
7454 }
7455
7456 /**
7457  * mono_property_get_object:
7458  * @domain: an app domain
7459  * @klass: a type
7460  * @property: a property
7461  * @error: set on error
7462  *
7463  * Return an System.Reflection.MonoProperty object representing the property @property
7464  * in class @klass.  On error returns NULL and sets @error.
7465  */
7466 MonoReflectionProperty*
7467 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7468 {
7469         MonoReflectionProperty *res;
7470
7471         mono_error_init (error);
7472
7473         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7474         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7475         if (!res)
7476                 return NULL;
7477         res->klass = klass;
7478         res->property = property;
7479         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7480 }
7481
7482 /*
7483  * mono_event_get_object:
7484  * @domain: an app domain
7485  * @klass: a type
7486  * @event: a event
7487  *
7488  * Return an System.Reflection.MonoEvent object representing the event @event
7489  * in class @klass.
7490  */
7491 MonoReflectionEvent*
7492 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7493 {
7494         MonoError error;
7495         MonoReflectionEvent *result;
7496         result = mono_event_get_object_checked (domain, klass, event, &error);
7497         mono_error_raise_exception (&error);
7498         return result;
7499 }
7500
7501 /**
7502  * mono_event_get_object_checked:
7503  * @domain: an app domain
7504  * @klass: a type
7505  * @event: a event
7506  * @error: set on error
7507  *
7508  * Return an System.Reflection.MonoEvent object representing the event @event
7509  * in class @klass. On failure sets @error and returns NULL
7510  */
7511 MonoReflectionEvent*
7512 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7513 {
7514         MonoReflectionEvent *res;
7515         MonoReflectionMonoEvent *mono_event;
7516
7517         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7518         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7519         if (!mono_event)
7520                 return NULL;
7521         mono_event->klass = klass;
7522         mono_event->event = event;
7523         res = (MonoReflectionEvent*)mono_event;
7524         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7525 }
7526
7527 /**
7528  * mono_get_reflection_missing_object:
7529  * @domain: Domain where the object lives
7530  *
7531  * Returns the System.Reflection.Missing.Value singleton object
7532  * (of type System.Reflection.Missing).
7533  *
7534  * Used as the value for ParameterInfo.DefaultValue when Optional
7535  * is present
7536  */
7537 static MonoObject *
7538 mono_get_reflection_missing_object (MonoDomain *domain)
7539 {
7540         MonoObject *obj;
7541         static MonoClassField *missing_value_field = NULL;
7542         
7543         if (!missing_value_field) {
7544                 MonoClass *missing_klass;
7545                 missing_klass = mono_class_get_missing_class ();
7546                 mono_class_init (missing_klass);
7547                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7548                 g_assert (missing_value_field);
7549         }
7550         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7551         g_assert (obj);
7552         return obj;
7553 }
7554
7555 static MonoObject*
7556 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7557 {
7558         if (!*dbnull)
7559                 *dbnull = mono_get_dbnull_object (domain);
7560         return *dbnull;
7561 }
7562
7563 static MonoObject*
7564 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7565 {
7566         if (!*reflection_missing)
7567                 *reflection_missing = mono_get_reflection_missing_object (domain);
7568         return *reflection_missing;
7569 }
7570
7571 /*
7572  * mono_param_get_objects:
7573  * @domain: an app domain
7574  * @method: a method
7575  *
7576  * Return an System.Reflection.ParameterInfo array object representing the parameters
7577  * in the method @method.
7578  */
7579 MonoArray*
7580 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7581 {
7582         static MonoClass *System_Reflection_ParameterInfo;
7583         static MonoClass *System_Reflection_ParameterInfo_array;
7584         MonoError error;
7585         MonoArray *res = NULL;
7586         MonoReflectionMethod *member = NULL;
7587         MonoReflectionParameter *param = NULL;
7588         char **names = NULL, **blobs = NULL;
7589         guint32 *types = NULL;
7590         MonoType *type = NULL;
7591         MonoObject *dbnull = NULL;
7592         MonoObject *missing = NULL;
7593         MonoMarshalSpec **mspecs = NULL;
7594         MonoMethodSignature *sig = NULL;
7595         MonoVTable *pinfo_vtable;
7596         MonoReflectionType *rt;
7597         int i;
7598
7599         mono_error_init (&error);
7600         
7601         if (!System_Reflection_ParameterInfo_array) {
7602                 MonoClass *klass;
7603
7604                 klass = mono_class_get_mono_parameter_info_class ();
7605
7606                 mono_memory_barrier ();
7607                 System_Reflection_ParameterInfo = klass; 
7608
7609         
7610                 klass = mono_array_class_get (klass, 1);
7611                 mono_memory_barrier ();
7612                 System_Reflection_ParameterInfo_array = klass;
7613         }
7614
7615         sig = mono_method_signature_checked (method, &error);
7616         if (!mono_error_ok (&error))
7617                 goto leave;
7618
7619         if (!sig->param_count) {
7620                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7621                 if (!res)
7622                         goto leave;
7623
7624                 return res;
7625         }
7626
7627         /* Note: the cache is based on the address of the signature into the method
7628          * since we already cache MethodInfos with the method as keys.
7629          */
7630         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7631
7632         member = mono_method_get_object_checked (domain, method, refclass, &error);
7633         if (!member)
7634                 goto leave;
7635         names = g_new (char *, sig->param_count);
7636         mono_method_get_param_names (method, (const char **) names);
7637
7638         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7639         mono_method_get_marshal_info (method, mspecs);
7640
7641         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7642         if (!res)
7643                 goto leave;
7644
7645         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7646         for (i = 0; i < sig->param_count; ++i) {
7647                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7648                 if (!param)
7649                         goto leave;
7650
7651                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7652                 if (!rt)
7653                         goto leave;
7654
7655                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7656
7657                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7658
7659                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7660
7661                 param->PositionImpl = i;
7662                 param->AttrsImpl = sig->params [i]->attrs;
7663
7664                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7665                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7666                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7667                         else
7668                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7669                 } else {
7670
7671                         if (!blobs) {
7672                                 blobs = g_new0 (char *, sig->param_count);
7673                                 types = g_new0 (guint32, sig->param_count);
7674                                 get_default_param_value_blobs (method, blobs, types); 
7675                         }
7676
7677                         /* Build MonoType for the type from the Constant Table */
7678                         if (!type)
7679                                 type = g_new0 (MonoType, 1);
7680                         type->type = (MonoTypeEnum)types [i];
7681                         type->data.klass = NULL;
7682                         if (types [i] == MONO_TYPE_CLASS)
7683                                 type->data.klass = mono_defaults.object_class;
7684                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7685                                 /* For enums, types [i] contains the base type */
7686
7687                                         type->type = MONO_TYPE_VALUETYPE;
7688                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7689                         } else
7690                                 type->data.klass = mono_class_from_mono_type (type);
7691
7692                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7693
7694                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7695                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7696                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7697                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7698                                 else
7699                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7700                         }
7701                         
7702                 }
7703
7704                 if (mspecs [i + 1]) {
7705                         MonoReflectionMarshalAsAttribute* mobj;
7706                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7707                         if (!mobj)
7708                                 goto leave;
7709                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7710                 }
7711                 
7712                 mono_array_setref (res, i, param);
7713         }
7714
7715 leave:
7716         g_free (names);
7717         g_free (blobs);
7718         g_free (types);
7719         g_free (type);
7720
7721         if (sig) {
7722                 for (i = sig->param_count; i >= 0; i--) {
7723                         if (mspecs [i])
7724                                 mono_metadata_free_marshal_spec (mspecs [i]);
7725                 }
7726         }
7727         g_free (mspecs);
7728
7729         mono_error_raise_exception (&error); /* FIXME don't raise here */
7730         
7731         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7732 }
7733
7734 MonoArray*
7735 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7736 {
7737         return mono_param_get_objects_internal (domain, method, NULL);
7738 }
7739
7740 /*
7741  * mono_method_body_get_object:
7742  * @domain: an app domain
7743  * @method: a method
7744  *
7745  * Return an System.Reflection.MethodBody object representing the method @method.
7746  */
7747 MonoReflectionMethodBody*
7748 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7749 {
7750         MonoError error;
7751         MonoReflectionMethodBody *ret;
7752         MonoMethodHeader *header;
7753         MonoImage *image;
7754         MonoReflectionType *rt;
7755         guint32 method_rva, local_var_sig_token;
7756     char *ptr;
7757         unsigned char format, flags;
7758         int i;
7759
7760         /* for compatibility with .net */
7761     if (method_is_dynamic (method))
7762         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7763
7764         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7765
7766         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7767                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7768             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7769                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7770             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7771                 return NULL;
7772
7773         image = method->klass->image;
7774         header = mono_method_get_header_checked (method, &error);
7775         mono_error_raise_exception (&error); /* FIXME don't raise here */
7776
7777         if (!image_is_dynamic (image)) {
7778                 /* Obtain local vars signature token */
7779                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7780                 ptr = mono_image_rva_map (image, method_rva);
7781                 flags = *(const unsigned char *) ptr;
7782                 format = flags & METHOD_HEADER_FORMAT_MASK;
7783                 switch (format){
7784                 case METHOD_HEADER_TINY_FORMAT:
7785                         local_var_sig_token = 0;
7786                         break;
7787                 case METHOD_HEADER_FAT_FORMAT:
7788                         ptr += 2;
7789                         ptr += 2;
7790                         ptr += 4;
7791                         local_var_sig_token = read32 (ptr);
7792                         break;
7793                 default:
7794                         g_assert_not_reached ();
7795                 }
7796         } else
7797                 local_var_sig_token = 0; //FIXME
7798
7799         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7800         mono_error_raise_exception (&error); /* FIXME don't raise here */
7801
7802         ret->init_locals = header->init_locals;
7803         ret->max_stack = header->max_stack;
7804         ret->local_var_sig_token = local_var_sig_token;
7805         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7806         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7807
7808         /* Locals */
7809         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7810         for (i = 0; i < header->num_locals; ++i) {
7811                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7812                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7813
7814                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7815                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7816
7817                 MONO_OBJECT_SETREF (info, local_type, rt);
7818
7819                 info->is_pinned = header->locals [i]->pinned;
7820                 info->local_index = i;
7821                 mono_array_setref (ret->locals, i, info);
7822         }
7823
7824         /* Exceptions */
7825         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7826         for (i = 0; i < header->num_clauses; ++i) {
7827                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7828                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7829                 MonoExceptionClause *clause = &header->clauses [i];
7830
7831                 info->flags = clause->flags;
7832                 info->try_offset = clause->try_offset;
7833                 info->try_length = clause->try_len;
7834                 info->handler_offset = clause->handler_offset;
7835                 info->handler_length = clause->handler_len;
7836                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7837                         info->filter_offset = clause->data.filter_offset;
7838                 else if (clause->data.catch_class) {
7839                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7840                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7841
7842                         MONO_OBJECT_SETREF (info, catch_type, rt);
7843                 }
7844
7845                 mono_array_setref (ret->clauses, i, info);
7846         }
7847
7848         mono_metadata_free_mh (header);
7849         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7850         return ret;
7851 }
7852
7853 /**
7854  * mono_get_dbnull_object:
7855  * @domain: Domain where the object lives
7856  *
7857  * Returns the System.DBNull.Value singleton object
7858  *
7859  * Used as the value for ParameterInfo.DefaultValue 
7860  */
7861 MonoObject *
7862 mono_get_dbnull_object (MonoDomain *domain)
7863 {
7864         MonoObject *obj;
7865         static MonoClassField *dbnull_value_field = NULL;
7866         
7867         if (!dbnull_value_field) {
7868                 MonoClass *dbnull_klass;
7869                 dbnull_klass = mono_class_get_dbnull_class ();
7870                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7871                 g_assert (dbnull_value_field);
7872         }
7873         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7874         g_assert (obj);
7875         return obj;
7876 }
7877
7878 static void
7879 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7880 {
7881         guint32 param_index, i, lastp, crow = 0;
7882         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7883         gint32 idx;
7884
7885         MonoClass *klass = method->klass;
7886         MonoImage *image = klass->image;
7887         MonoMethodSignature *methodsig = mono_method_signature (method);
7888
7889         MonoTableInfo *constt;
7890         MonoTableInfo *methodt;
7891         MonoTableInfo *paramt;
7892
7893         if (!methodsig->param_count)
7894                 return;
7895
7896         mono_class_init (klass);
7897
7898         if (image_is_dynamic (klass->image)) {
7899                 MonoReflectionMethodAux *aux;
7900                 if (method->is_inflated)
7901                         method = ((MonoMethodInflated*)method)->declaring;
7902                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7903                 if (aux && aux->param_defaults) {
7904                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7905                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7906                 }
7907                 return;
7908         }
7909
7910         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7911         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7912         constt = &image->tables [MONO_TABLE_CONSTANT];
7913
7914         idx = mono_method_get_index (method) - 1;
7915         g_assert (idx != -1);
7916
7917         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7918         if (idx + 1 < methodt->rows)
7919                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7920         else
7921                 lastp = paramt->rows + 1;
7922
7923         for (i = param_index; i < lastp; ++i) {
7924                 guint32 paramseq;
7925
7926                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7927                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7928
7929                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7930                         continue;
7931
7932                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7933                 if (!crow) {
7934                         continue;
7935                 }
7936         
7937                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7938                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7939                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7940         }
7941
7942         return;
7943 }
7944
7945 MonoObject *
7946 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7947 {
7948         MonoError error;
7949         void *retval;
7950         MonoClass *klass;
7951         MonoObject *object;
7952         MonoType *basetype = type;
7953
7954         if (!blob)
7955                 return NULL;
7956         
7957         klass = mono_class_from_mono_type (type);
7958         if (klass->valuetype) {
7959                 object = mono_object_new_checked (domain, klass, &error);
7960                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7961                 retval = ((gchar *) object + sizeof (MonoObject));
7962                 if (klass->enumtype)
7963                         basetype = mono_class_enum_basetype (klass);
7964         } else {
7965                 retval = &object;
7966         }
7967                         
7968         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7969                 return object;
7970         else
7971                 return NULL;
7972 }
7973
7974 static int
7975 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7976         int found_sep;
7977         char *s;
7978         gboolean quoted = FALSE;
7979
7980         memset (assembly, 0, sizeof (MonoAssemblyName));
7981         assembly->culture = "";
7982         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7983
7984         if (*p == '"') {
7985                 quoted = TRUE;
7986                 p++;
7987         }
7988         assembly->name = p;
7989         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7990                 p++;
7991         if (quoted) {
7992                 if (*p != '"')
7993                         return 1;
7994                 *p = 0;
7995                 p++;
7996         }
7997         if (*p != ',')
7998                 return 1;
7999         *p = 0;
8000         /* Remove trailing whitespace */
8001         s = p - 1;
8002         while (*s && g_ascii_isspace (*s))
8003                 *s-- = 0;
8004         p ++;
8005         while (g_ascii_isspace (*p))
8006                 p++;
8007         while (*p) {
8008                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
8009                         p += 8;
8010                         assembly->major = strtoul (p, &s, 10);
8011                         if (s == p || *s != '.')
8012                                 return 1;
8013                         p = ++s;
8014                         assembly->minor = strtoul (p, &s, 10);
8015                         if (s == p || *s != '.')
8016                                 return 1;
8017                         p = ++s;
8018                         assembly->build = strtoul (p, &s, 10);
8019                         if (s == p || *s != '.')
8020                                 return 1;
8021                         p = ++s;
8022                         assembly->revision = strtoul (p, &s, 10);
8023                         if (s == p)
8024                                 return 1;
8025                         p = s;
8026                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
8027                         p += 8;
8028                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
8029                                 assembly->culture = "";
8030                                 p += 7;
8031                         } else {
8032                                 assembly->culture = p;
8033                                 while (*p && *p != ',') {
8034                                         p++;
8035                                 }
8036                         }
8037                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
8038                         p += 15;
8039                         if (strncmp (p, "null", 4) == 0) {
8040                                 p += 4;
8041                         } else {
8042                                 int len;
8043                                 gchar *start = p;
8044                                 while (*p && *p != ',') {
8045                                         p++;
8046                                 }
8047                                 len = (p - start + 1);
8048                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
8049                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
8050                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
8051                         }
8052                 } else {
8053                         while (*p && *p != ',')
8054                                 p++;
8055                 }
8056                 found_sep = 0;
8057                 while (g_ascii_isspace (*p) || *p == ',') {
8058                         *p++ = 0;
8059                         found_sep = 1;
8060                         continue;
8061                 }
8062                 /* failed */
8063                 if (!found_sep)
8064                         return 1;
8065         }
8066
8067         return 0;
8068 }
8069
8070 /*
8071  * mono_reflection_parse_type:
8072  * @name: type name
8073  *
8074  * Parse a type name as accepted by the GetType () method and output the info
8075  * extracted in the info structure.
8076  * the name param will be mangled, so, make a copy before passing it to this function.
8077  * The fields in info will be valid until the memory pointed to by name is valid.
8078  *
8079  * See also mono_type_get_name () below.
8080  *
8081  * Returns: 0 on parse error.
8082  */
8083 static int
8084 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
8085                              MonoTypeNameParse *info)
8086 {
8087         char *start, *p, *w, *last_point, *startn;
8088         int in_modifiers = 0;
8089         int isbyref = 0, rank = 0, isptr = 0;
8090
8091         start = p = w = name;
8092
8093         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
8094         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
8095         info->name = info->name_space = NULL;
8096         info->nested = NULL;
8097         info->modifiers = NULL;
8098         info->type_arguments = NULL;
8099
8100         /* last_point separates the namespace from the name */
8101         last_point = NULL;
8102         /* Skips spaces */
8103         while (*p == ' ') p++, start++, w++, name++;
8104
8105         while (*p) {
8106                 switch (*p) {
8107                 case '+':
8108                         *p = 0; /* NULL terminate the name */
8109                         startn = p + 1;
8110                         info->nested = g_list_append (info->nested, startn);
8111                         /* we have parsed the nesting namespace + name */
8112                         if (info->name)
8113                                 break;
8114                         if (last_point) {
8115                                 info->name_space = start;
8116                                 *last_point = 0;
8117                                 info->name = last_point + 1;
8118                         } else {
8119                                 info->name_space = (char *)"";
8120                                 info->name = start;
8121                         }
8122                         break;
8123                 case '.':
8124                         last_point = p;
8125                         break;
8126                 case '\\':
8127                         ++p;
8128                         break;
8129                 case '&':
8130                 case '*':
8131                 case '[':
8132                 case ',':
8133                 case ']':
8134                         in_modifiers = 1;
8135                         break;
8136                 default:
8137                         break;
8138                 }
8139                 if (in_modifiers)
8140                         break;
8141                 // *w++ = *p++;
8142                 p++;
8143         }
8144         
8145         if (!info->name) {
8146                 if (last_point) {
8147                         info->name_space = start;
8148                         *last_point = 0;
8149                         info->name = last_point + 1;
8150                 } else {
8151                         info->name_space = (char *)"";
8152                         info->name = start;
8153                 }
8154         }
8155         while (*p) {
8156                 switch (*p) {
8157                 case '&':
8158                         if (isbyref) /* only one level allowed by the spec */
8159                                 return 0;
8160                         isbyref = 1;
8161                         isptr = 0;
8162                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
8163                         *p++ = 0;
8164                         break;
8165                 case '*':
8166                         if (isbyref) /* pointer to ref not okay */
8167                                 return 0;
8168                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
8169                         isptr = 1;
8170                         *p++ = 0;
8171                         break;
8172                 case '[':
8173                         if (isbyref) /* array of ref and generic ref are not okay */
8174                                 return 0;
8175                         //Decide if it's an array of a generic argument list
8176                         *p++ = 0;
8177
8178                         if (!*p) //XXX test
8179                                 return 0;
8180                         if (*p  == ',' || *p == '*' || *p == ']') { //array
8181                                 isptr = 0;
8182                                 rank = 1;
8183                                 while (*p) {
8184                                         if (*p == ']')
8185                                                 break;
8186                                         if (*p == ',')
8187                                                 rank++;
8188                                         else if (*p == '*') /* '*' means unknown lower bound */
8189                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
8190                                         else
8191                                                 return 0;
8192                                         ++p;
8193                                 }
8194                                 if (*p++ != ']')
8195                                         return 0;
8196                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
8197                         } else {
8198                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
8199                                         return 0;
8200                                 isptr = 0;
8201                                 info->type_arguments = g_ptr_array_new ();
8202                                 while (*p) {
8203                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
8204                                         gboolean fqname = FALSE;
8205
8206                                         g_ptr_array_add (info->type_arguments, subinfo);
8207
8208                                         while (*p == ' ') p++;
8209                                         if (*p == '[') {
8210                                                 p++;
8211                                                 fqname = TRUE;
8212                                         }
8213
8214                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
8215                                                 return 0;
8216
8217                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
8218                                         if (fqname && (*p != ']')) {
8219                                                 char *aname;
8220
8221                                                 if (*p != ',')
8222                                                         return 0;
8223                                                 *p++ = 0;
8224
8225                                                 aname = p;
8226                                                 while (*p && (*p != ']'))
8227                                                         p++;
8228
8229                                                 if (*p != ']')
8230                                                         return 0;
8231
8232                                                 *p++ = 0;
8233                                                 while (*aname) {
8234                                                         if (g_ascii_isspace (*aname)) {
8235                                                                 ++aname;
8236                                                                 continue;
8237                                                         }
8238                                                         break;
8239                                                 }
8240                                                 if (!*aname ||
8241                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8242                                                         return 0;
8243                                         } else if (fqname && (*p == ']')) {
8244                                                 *p++ = 0;
8245                                         }
8246                                         if (*p == ']') {
8247                                                 *p++ = 0;
8248                                                 break;
8249                                         } else if (!*p) {
8250                                                 return 0;
8251                                         }
8252                                         *p++ = 0;
8253                                 }
8254                         }
8255                         break;
8256                 case ']':
8257                         if (is_recursed)
8258                                 goto end;
8259                         return 0;
8260                 case ',':
8261                         if (is_recursed)
8262                                 goto end;
8263                         *p++ = 0;
8264                         while (*p) {
8265                                 if (g_ascii_isspace (*p)) {
8266                                         ++p;
8267                                         continue;
8268                                 }
8269                                 break;
8270                         }
8271                         if (!*p)
8272                                 return 0; /* missing assembly name */
8273                         if (!assembly_name_to_aname (&info->assembly, p))
8274                                 return 0;
8275                         break;
8276                 default:
8277                         return 0;
8278                 }
8279                 if (info->assembly.name)
8280                         break;
8281         }
8282         // *w = 0; /* terminate class name */
8283  end:
8284         if (!info->name || !*info->name)
8285                 return 0;
8286         if (endptr)
8287                 *endptr = p;
8288         /* add other consistency checks */
8289         return 1;
8290 }
8291
8292
8293 /**
8294  * mono_identifier_unescape_type_name_chars:
8295  * @identifier: the display name of a mono type
8296  *
8297  * Returns:
8298  *  The name in internal form, that is without escaping backslashes.
8299  *
8300  *  The string is modified in place!
8301  */
8302 char*
8303 mono_identifier_unescape_type_name_chars(char* identifier)
8304 {
8305         char *w, *r;
8306         if (!identifier)
8307                 return NULL;
8308         for (w = r = identifier; *r != 0; r++)
8309         {
8310                 char c = *r;
8311                 if (c == '\\') {
8312                         r++;
8313                         if (*r == 0)
8314                                 break;
8315                         c = *r;
8316                 }
8317                 *w = c;
8318                 w++;
8319         }
8320         if (w != r)
8321                 *w = 0;
8322         return identifier;
8323 }
8324
8325 void
8326 mono_identifier_unescape_info (MonoTypeNameParse* info);
8327
8328 static void
8329 unescape_each_type_argument(void* data, void* user_data)
8330 {
8331         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8332         mono_identifier_unescape_info (info);
8333 }
8334
8335 static void
8336 unescape_each_nested_name (void* data, void* user_data)
8337 {
8338         char* nested_name = (char*) data;
8339         mono_identifier_unescape_type_name_chars(nested_name);
8340 }
8341
8342 /**
8343  * mono_identifier_unescape_info:
8344  *
8345  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8346  *
8347  * Returns: nothing.
8348  *
8349  * Destructively updates the info by unescaping the identifiers that
8350  * comprise the type namespace, name, nested types (if any) and
8351  * generic type arguments (if any).
8352  *
8353  * The resulting info has the names in internal form.
8354  *
8355  */
8356 void
8357 mono_identifier_unescape_info (MonoTypeNameParse *info)
8358 {
8359         if (!info)
8360                 return;
8361         mono_identifier_unescape_type_name_chars(info->name_space);
8362         mono_identifier_unescape_type_name_chars(info->name);
8363         // but don't escape info->assembly
8364         if (info->type_arguments)
8365                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8366         if (info->nested)
8367                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8368 }
8369
8370 int
8371 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8372 {
8373         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8374         if (ok) {
8375                 mono_identifier_unescape_info (info);
8376         }
8377         return ok;
8378 }
8379
8380 static MonoType*
8381 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8382 {
8383         gboolean type_resolve = FALSE;
8384         MonoType *type;
8385         MonoImage *rootimage = image;
8386
8387         if (info->assembly.name) {
8388                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8389                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8390                         /* 
8391                          * This could happen in the AOT compiler case when the search hook is not
8392                          * installed.
8393                          */
8394                         assembly = image->assembly;
8395                 if (!assembly) {
8396                         /* then we must load the assembly ourselve - see #60439 */
8397                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8398                         if (!assembly)
8399                                 return NULL;
8400                 }
8401                 image = assembly->image;
8402         } else if (!image) {
8403                 image = mono_defaults.corlib;
8404         }
8405
8406         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8407         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8408                 image = mono_defaults.corlib;
8409                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8410         }
8411
8412         return type;
8413 }
8414
8415 /**
8416  * mono_reflection_get_type_internal:
8417  *
8418  * Returns: may return NULL on success, sets error on failure.
8419  */
8420 static MonoType*
8421 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8422 {
8423         MonoClass *klass;
8424         GList *mod;
8425         int modval;
8426         gboolean bounded = FALSE;
8427         
8428         mono_error_init (error);
8429         if (!image)
8430                 image = mono_defaults.corlib;
8431
8432         if (!rootimage)
8433                 rootimage = mono_defaults.corlib;
8434
8435         if (ignorecase)
8436                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8437         else
8438                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8439
8440         if (!klass)
8441                 return NULL;
8442
8443         for (mod = info->nested; mod; mod = mod->next) {
8444                 gpointer iter = NULL;
8445                 MonoClass *parent;
8446
8447                 parent = klass;
8448                 mono_class_init (parent);
8449
8450                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8451                         char *lastp;
8452                         char *nested_name, *nested_nspace;
8453                         gboolean match = TRUE;
8454
8455                         lastp = strrchr ((const char *)mod->data, '.');
8456                         if (lastp) {
8457                                 /* Nested classes can have namespaces */
8458                                 int nspace_len;
8459
8460                                 nested_name = g_strdup (lastp + 1);
8461                                 nspace_len = lastp - (char*)mod->data;
8462                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8463                                 memcpy (nested_nspace, mod->data, nspace_len);
8464                                 nested_nspace [nspace_len] = '\0';
8465
8466                         } else {
8467                                 nested_name = (char *)mod->data;
8468                                 nested_nspace = NULL;
8469                         }
8470
8471                         if (nested_nspace) {
8472                                 if (ignorecase) {
8473                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8474                                                 match = FALSE;
8475                                 } else {
8476                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8477                                                 match = FALSE;
8478                                 }
8479                         }
8480                         if (match) {
8481                                 if (ignorecase) {
8482                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8483                                                 match = FALSE;
8484                                 } else {
8485                                         if (strcmp (klass->name, nested_name) != 0)
8486                                                 match = FALSE;
8487                                 }
8488                         }
8489                         if (lastp) {
8490                                 g_free (nested_name);
8491                                 g_free (nested_nspace);
8492                         }
8493                         if (match)
8494                                 break;
8495                 }
8496
8497                 if (!klass)
8498                         break;
8499         }
8500         if (!klass)
8501                 return NULL;
8502
8503         if (info->type_arguments) {
8504                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8505                 MonoReflectionType *the_type;
8506                 MonoType *instance;
8507                 int i;
8508
8509                 for (i = 0; i < info->type_arguments->len; i++) {
8510                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8511
8512                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8513                         if (!type_args [i]) {
8514                                 g_free (type_args);
8515                                 return NULL;
8516                         }
8517                 }
8518
8519                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8520                 if (!the_type)
8521                         return NULL;
8522
8523                 instance = mono_reflection_bind_generic_parameters (
8524                         the_type, info->type_arguments->len, type_args);
8525
8526                 g_free (type_args);
8527                 if (!instance)
8528                         return NULL;
8529
8530                 klass = mono_class_from_mono_type (instance);
8531         }
8532
8533         for (mod = info->modifiers; mod; mod = mod->next) {
8534                 modval = GPOINTER_TO_UINT (mod->data);
8535                 if (!modval) { /* byref: must be last modifier */
8536                         return &klass->this_arg;
8537                 } else if (modval == -1) {
8538                         klass = mono_ptr_class_get (&klass->byval_arg);
8539                 } else if (modval == -2) {
8540                         bounded = TRUE;
8541                 } else { /* array rank */
8542                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8543                 }
8544         }
8545
8546         return &klass->byval_arg;
8547 }
8548
8549 /*
8550  * mono_reflection_get_type:
8551  * @image: a metadata context
8552  * @info: type description structure
8553  * @ignorecase: flag for case-insensitive string compares
8554  * @type_resolve: whenever type resolve was already tried
8555  *
8556  * Build a MonoType from the type description in @info.
8557  * 
8558  */
8559
8560 MonoType*
8561 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8562         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8563 }
8564
8565 static MonoType*
8566 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8567 {
8568         MonoReflectionAssemblyBuilder *abuilder;
8569         MonoType *type;
8570         int i;
8571
8572         mono_error_init (error);
8573         g_assert (assembly_is_dynamic (assembly));
8574         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8575         if (!abuilder)
8576                 return NULL;
8577
8578         /* Enumerate all modules */
8579
8580         type = NULL;
8581         if (abuilder->modules) {
8582                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8583                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8584                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8585                         if (type)
8586                                 break;
8587                         if (!mono_error_ok (error))
8588                                 return NULL;
8589                 }
8590         }
8591
8592         if (!type && abuilder->loaded_modules) {
8593                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8594                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8595                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8596                         if (type)
8597                                 break;
8598                         if (!mono_error_ok (error))
8599                                 return NULL;
8600                 }
8601         }
8602
8603         return type;
8604 }
8605         
8606 MonoType*
8607 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8608 {
8609         MonoError error;
8610         MonoType *type;
8611         MonoReflectionAssembly *assembly;
8612         GString *fullName;
8613         GList *mod;
8614
8615         if (image && image_is_dynamic (image))
8616                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8617         else {
8618                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8619         }
8620         if (!mono_error_ok (&error))
8621                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8622
8623         if (type)
8624                 return type;
8625         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8626                 return NULL;
8627
8628         if (type_resolve) {
8629                 if (*type_resolve) 
8630                         return NULL;
8631                 else
8632                         *type_resolve = TRUE;
8633         }
8634         
8635         /* Reconstruct the type name */
8636         fullName = g_string_new ("");
8637         if (info->name_space && (info->name_space [0] != '\0'))
8638                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8639         else
8640                 g_string_printf (fullName, "%s", info->name);
8641         for (mod = info->nested; mod; mod = mod->next)
8642                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8643
8644         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8645         mono_error_raise_exception (&error); /* FIXME don't raise here */
8646
8647         if (assembly) {
8648                 if (assembly_is_dynamic (assembly->assembly))
8649                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8650                                                                           info, ignorecase, &error);
8651                 else
8652                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8653                                                                   info, ignorecase, &error);
8654         }
8655         g_string_free (fullName, TRUE);
8656         if (!mono_error_ok (&error))
8657                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8658         return type;
8659 }
8660
8661 void
8662 mono_reflection_free_type_info (MonoTypeNameParse *info)
8663 {
8664         g_list_free (info->modifiers);
8665         g_list_free (info->nested);
8666
8667         if (info->type_arguments) {
8668                 int i;
8669
8670                 for (i = 0; i < info->type_arguments->len; i++) {
8671                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8672
8673                         mono_reflection_free_type_info (subinfo);
8674                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8675                         g_free (subinfo);
8676                 }
8677
8678                 g_ptr_array_free (info->type_arguments, TRUE);
8679         }
8680 }
8681
8682 /*
8683  * mono_reflection_type_from_name:
8684  * @name: type name.
8685  * @image: a metadata context (can be NULL).
8686  *
8687  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8688  * it defaults to get the type from @image or, if @image is NULL or loading
8689  * from it fails, uses corlib.
8690  * 
8691  */
8692 MonoType*
8693 mono_reflection_type_from_name (char *name, MonoImage *image)
8694 {
8695         MonoType *type = NULL;
8696         MonoTypeNameParse info;
8697         char *tmp;
8698
8699         /* Make a copy since parse_type modifies its argument */
8700         tmp = g_strdup (name);
8701         
8702         /*g_print ("requested type %s\n", str);*/
8703         if (mono_reflection_parse_type (tmp, &info)) {
8704                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8705         }
8706
8707         g_free (tmp);
8708         mono_reflection_free_type_info (&info);
8709         return type;
8710 }
8711
8712 /*
8713  * mono_reflection_get_token:
8714  *
8715  *   Return the metadata token of OBJ which should be an object
8716  * representing a metadata element.
8717  */
8718 guint32
8719 mono_reflection_get_token (MonoObject *obj)
8720 {
8721         MonoError error;
8722         MonoClass *klass;
8723         guint32 token = 0;
8724
8725         klass = obj->vtable->klass;
8726
8727         if (strcmp (klass->name, "MethodBuilder") == 0) {
8728                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8729
8730                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8731         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8732                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8733
8734                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8735         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8736                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8737
8738                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8739         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8740                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8741                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8742         } else if (strcmp (klass->name, "MonoType") == 0) {
8743                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
8744                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8745                 MonoClass *mc = mono_class_from_mono_type (type);
8746                 if (!mono_class_init (mc))
8747                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8748
8749                 token = mc->type_token;
8750         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8751                    strcmp (klass->name, "MonoMethod") == 0 ||
8752                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8753                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8754                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8755                 if (m->method->is_inflated) {
8756                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8757                         return inflated->declaring->token;
8758                 } else {
8759                         token = m->method->token;
8760                 }
8761         } else if (strcmp (klass->name, "MonoField") == 0) {
8762                 MonoReflectionField *f = (MonoReflectionField*)obj;
8763
8764                 if (is_field_on_inst (f->field)) {
8765                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8766
8767                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8768                                 int field_index = f->field - dgclass->fields;
8769                                 MonoObject *obj;
8770
8771                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8772                                 obj = dgclass->field_objects [field_index];
8773                                 return mono_reflection_get_token (obj);
8774                         }
8775                 }
8776                 token = mono_class_get_field_token (f->field);
8777         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8778                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8779
8780                 token = mono_class_get_property_token (p->property);
8781         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8782                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8783
8784                 token = mono_class_get_event_token (p->event);
8785         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8786                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8787                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8788                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8789
8790                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8791         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8792                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8793
8794                 token = m->token;
8795         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8796                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8797         } else {
8798                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8799                 MonoException *ex = mono_get_exception_not_implemented (msg);
8800                 g_free (msg);
8801                 mono_raise_exception (ex);
8802         }
8803
8804         return token;
8805 }
8806
8807 static MonoClass*
8808 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8809 {
8810         char *n;
8811         MonoType *t;
8812         int slen = mono_metadata_decode_value (p, &p);
8813
8814         mono_error_init (error);
8815
8816         n = (char *)g_memdup (p, slen + 1);
8817         n [slen] = 0;
8818         t = mono_reflection_type_from_name (n, image);
8819         if (!t) {
8820                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8821                 /* We don't free n, it's consumed by mono_error */
8822                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8823                 return NULL;
8824         }
8825         g_free (n);
8826         p += slen;
8827         *end = p;
8828         return mono_class_from_mono_type (t);
8829 }
8830
8831 static void*
8832 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8833 {
8834         int slen, type = t->type;
8835         MonoClass *tklass = t->data.klass;
8836
8837         mono_error_init (error);
8838
8839 handle_enum:
8840         switch (type) {
8841         case MONO_TYPE_U1:
8842         case MONO_TYPE_I1:
8843         case MONO_TYPE_BOOLEAN: {
8844                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8845                 *bval = *p;
8846                 *end = p + 1;
8847                 return bval;
8848         }
8849         case MONO_TYPE_CHAR:
8850         case MONO_TYPE_U2:
8851         case MONO_TYPE_I2: {
8852                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8853                 *val = read16 (p);
8854                 *end = p + 2;
8855                 return val;
8856         }
8857 #if SIZEOF_VOID_P == 4
8858         case MONO_TYPE_U:
8859         case MONO_TYPE_I:
8860 #endif
8861         case MONO_TYPE_R4:
8862         case MONO_TYPE_U4:
8863         case MONO_TYPE_I4: {
8864                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8865                 *val = read32 (p);
8866                 *end = p + 4;
8867                 return val;
8868         }
8869 #if SIZEOF_VOID_P == 8
8870         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8871         case MONO_TYPE_I:
8872 #endif
8873         case MONO_TYPE_U8:
8874         case MONO_TYPE_I8: {
8875                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8876                 *val = read64 (p);
8877                 *end = p + 8;
8878                 return val;
8879         }
8880         case MONO_TYPE_R8: {
8881                 double *val = (double *)g_malloc (sizeof (double));
8882                 readr8 (p, val);
8883                 *end = p + 8;
8884                 return val;
8885         }
8886         case MONO_TYPE_VALUETYPE:
8887                 if (t->data.klass->enumtype) {
8888                         type = mono_class_enum_basetype (t->data.klass)->type;
8889                         goto handle_enum;
8890                 } else {
8891                         MonoClass *k =  t->data.klass;
8892                         
8893                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8894                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8895                                 *val = read64 (p);
8896                                 *end = p + 8;
8897                                 return val;
8898                         }
8899                 }
8900                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8901                 break;
8902                 
8903         case MONO_TYPE_STRING:
8904                 if (*p == (char)0xFF) {
8905                         *end = p + 1;
8906                         return NULL;
8907                 }
8908                 slen = mono_metadata_decode_value (p, &p);
8909                 *end = p + slen;
8910                 return mono_string_new_len (mono_domain_get (), p, slen);
8911         case MONO_TYPE_CLASS: {
8912                 MonoReflectionType *rt;
8913                 char *n;
8914                 MonoType *t;
8915                 if (*p == (char)0xFF) {
8916                         *end = p + 1;
8917                         return NULL;
8918                 }
8919 handle_type:
8920                 slen = mono_metadata_decode_value (p, &p);
8921                 n = (char *)g_memdup (p, slen + 1);
8922                 n [slen] = 0;
8923                 t = mono_reflection_type_from_name (n, image);
8924                 if (!t) {
8925                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8926                         /* We don't free n, it's consumed by mono_error */
8927                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8928                         return NULL;
8929                 }
8930                 g_free (n);
8931                 *end = p + slen;
8932
8933                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8934                 if (!mono_error_ok (error))
8935                         return NULL;
8936
8937                 return rt;
8938         }
8939         case MONO_TYPE_OBJECT: {
8940                 char subt = *p++;
8941                 MonoObject *obj;
8942                 MonoClass *subc = NULL;
8943                 void *val;
8944
8945                 if (subt == 0x50) {
8946                         goto handle_type;
8947                 } else if (subt == 0x0E) {
8948                         type = MONO_TYPE_STRING;
8949                         goto handle_enum;
8950                 } else if (subt == 0x1D) {
8951                         MonoType simple_type = {{0}};
8952                         int etype = *p;
8953                         p ++;
8954
8955                         type = MONO_TYPE_SZARRAY;
8956                         if (etype == 0x50) {
8957                                 tklass = mono_defaults.systemtype_class;
8958                         } else if (etype == 0x55) {
8959                                 tklass = load_cattr_enum_type (image, p, &p, error);
8960                                 if (!mono_error_ok (error))
8961                                         return NULL;
8962                         } else {
8963                                 if (etype == 0x51)
8964                                         /* See Partition II, Appendix B3 */
8965                                         etype = MONO_TYPE_OBJECT;
8966                                 simple_type.type = (MonoTypeEnum)etype;
8967                                 tklass = mono_class_from_mono_type (&simple_type);
8968                         }
8969                         goto handle_enum;
8970                 } else if (subt == 0x55) {
8971                         char *n;
8972                         MonoType *t;
8973                         slen = mono_metadata_decode_value (p, &p);
8974                         n = (char *)g_memdup (p, slen + 1);
8975                         n [slen] = 0;
8976                         t = mono_reflection_type_from_name (n, image);
8977                         if (!t) {
8978                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8979                                 /* We don't free n, it's consumed by mono_error */
8980                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8981                                 return NULL;
8982                         }
8983                         g_free (n);
8984                         p += slen;
8985                         subc = mono_class_from_mono_type (t);
8986                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8987                         MonoType simple_type = {{0}};
8988                         simple_type.type = (MonoTypeEnum)subt;
8989                         subc = mono_class_from_mono_type (&simple_type);
8990                 } else {
8991                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8992                 }
8993                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8994                 obj = NULL;
8995                 if (mono_error_ok (error)) {
8996                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8997                         g_assert (!subc->has_references);
8998                         if (mono_error_ok (error))
8999                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
9000                 }
9001
9002                 g_free (val);
9003                 return obj;
9004         }
9005         case MONO_TYPE_SZARRAY: {
9006                 MonoArray *arr;
9007                 guint32 i, alen, basetype;
9008                 alen = read32 (p);
9009                 p += 4;
9010                 if (alen == 0xffffffff) {
9011                         *end = p;
9012                         return NULL;
9013                 }
9014                 arr = mono_array_new (mono_domain_get(), tklass, alen);
9015                 basetype = tklass->byval_arg.type;
9016                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
9017                         basetype = mono_class_enum_basetype (tklass)->type;
9018                 switch (basetype)
9019                 {
9020                         case MONO_TYPE_U1:
9021                         case MONO_TYPE_I1:
9022                         case MONO_TYPE_BOOLEAN:
9023                                 for (i = 0; i < alen; i++) {
9024                                         MonoBoolean val = *p++;
9025                                         mono_array_set (arr, MonoBoolean, i, val);
9026                                 }
9027                                 break;
9028                         case MONO_TYPE_CHAR:
9029                         case MONO_TYPE_U2:
9030                         case MONO_TYPE_I2:
9031                                 for (i = 0; i < alen; i++) {
9032                                         guint16 val = read16 (p);
9033                                         mono_array_set (arr, guint16, i, val);
9034                                         p += 2;
9035                                 }
9036                                 break;
9037                         case MONO_TYPE_R4:
9038                         case MONO_TYPE_U4:
9039                         case MONO_TYPE_I4:
9040                                 for (i = 0; i < alen; i++) {
9041                                         guint32 val = read32 (p);
9042                                         mono_array_set (arr, guint32, i, val);
9043                                         p += 4;
9044                                 }
9045                                 break;
9046                         case MONO_TYPE_R8:
9047                                 for (i = 0; i < alen; i++) {
9048                                         double val;
9049                                         readr8 (p, &val);
9050                                         mono_array_set (arr, double, i, val);
9051                                         p += 8;
9052                                 }
9053                                 break;
9054                         case MONO_TYPE_U8:
9055                         case MONO_TYPE_I8:
9056                                 for (i = 0; i < alen; i++) {
9057                                         guint64 val = read64 (p);
9058                                         mono_array_set (arr, guint64, i, val);
9059                                         p += 8;
9060                                 }
9061                                 break;
9062                         case MONO_TYPE_CLASS:
9063                         case MONO_TYPE_OBJECT:
9064                         case MONO_TYPE_STRING:
9065                         case MONO_TYPE_SZARRAY:
9066                                 for (i = 0; i < alen; i++) {
9067                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
9068                                         if (!mono_error_ok (error))
9069                                                 return NULL;
9070                                         mono_array_setref (arr, i, item);
9071                                 }
9072                                 break;
9073                         default:
9074                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
9075                 }
9076                 *end=p;
9077                 return arr;
9078         }
9079         default:
9080                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
9081         }
9082         return NULL;
9083 }
9084
9085 static MonoObject*
9086 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
9087 {
9088         static MonoMethod *ctor;
9089         MonoObject *retval;
9090         void *params [2], *unboxed;
9091
9092         mono_error_init (error);
9093
9094         if (!ctor)
9095                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
9096         
9097         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
9098         return_val_if_nok (error, NULL);
9099
9100         params [1] = val;
9101         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
9102         return_val_if_nok (error, NULL);
9103         unboxed = mono_object_unbox (retval);
9104
9105         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9106         return_val_if_nok (error, NULL);
9107
9108         return retval;
9109 }
9110
9111 static MonoObject*
9112 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
9113 {
9114         static MonoMethod *ctor;
9115         MonoObject *retval;
9116         void *unboxed, *params [2];
9117
9118         mono_error_init (error);
9119
9120         if (!ctor)
9121                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
9122
9123         params [0] = minfo;
9124         params [1] = typedarg;
9125         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
9126         return_val_if_nok (error, NULL);
9127
9128         unboxed = mono_object_unbox (retval);
9129
9130         mono_runtime_invoke_checked (ctor, unboxed, params, error);
9131         return_val_if_nok (error, NULL);
9132
9133         return retval;
9134 }
9135
9136 static gboolean
9137 type_is_reference (MonoType *type)
9138 {
9139         switch (type->type) {
9140         case MONO_TYPE_BOOLEAN:
9141         case MONO_TYPE_CHAR:
9142         case MONO_TYPE_U:
9143         case MONO_TYPE_I:
9144         case MONO_TYPE_U1:
9145         case MONO_TYPE_I1:
9146         case MONO_TYPE_U2:
9147         case MONO_TYPE_I2:
9148         case MONO_TYPE_U4:
9149         case MONO_TYPE_I4:
9150         case MONO_TYPE_U8:
9151         case MONO_TYPE_I8:
9152         case MONO_TYPE_R8:
9153         case MONO_TYPE_R4:
9154         case MONO_TYPE_VALUETYPE:
9155                 return FALSE;
9156         default:
9157                 return TRUE;
9158         }
9159 }
9160
9161 static void
9162 free_param_data (MonoMethodSignature *sig, void **params) {
9163         int i;
9164         for (i = 0; i < sig->param_count; ++i) {
9165                 if (!type_is_reference (sig->params [i]))
9166                         g_free (params [i]);
9167         }
9168 }
9169
9170 /*
9171  * Find the field index in the metadata FieldDef table.
9172  */
9173 static guint32
9174 find_field_index (MonoClass *klass, MonoClassField *field) {
9175         int i;
9176
9177         for (i = 0; i < klass->field.count; ++i) {
9178                 if (field == &klass->fields [i])
9179                         return klass->field.first + 1 + i;
9180         }
9181         return 0;
9182 }
9183
9184 /*
9185  * Find the property index in the metadata Property table.
9186  */
9187 static guint32
9188 find_property_index (MonoClass *klass, MonoProperty *property) {
9189         int i;
9190
9191         for (i = 0; i < klass->ext->property.count; ++i) {
9192                 if (property == &klass->ext->properties [i])
9193                         return klass->ext->property.first + 1 + i;
9194         }
9195         return 0;
9196 }
9197
9198 /*
9199  * Find the event index in the metadata Event table.
9200  */
9201 static guint32
9202 find_event_index (MonoClass *klass, MonoEvent *event) {
9203         int i;
9204
9205         for (i = 0; i < klass->ext->event.count; ++i) {
9206                 if (event == &klass->ext->events [i])
9207                         return klass->ext->event.first + 1 + i;
9208         }
9209         return 0;
9210 }
9211
9212 static MonoObject*
9213 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
9214 {
9215         const char *p = (const char*)data;
9216         const char *named;
9217         guint32 i, j, num_named;
9218         MonoObject *attr;
9219         void *params_buf [32];
9220         void **params = NULL;
9221         MonoMethodSignature *sig;
9222         MonoObject *exc = NULL;
9223
9224         mono_error_init (error);
9225
9226         mono_class_init (method->klass);
9227
9228         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9229                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9230                 return NULL;
9231         }
9232
9233         if (len == 0) {
9234                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9235                 if (!mono_error_ok (error)) return NULL;
9236
9237                 mono_runtime_invoke_checked (method, attr, NULL, error);
9238                 if (!mono_error_ok (error))
9239                         return NULL;
9240
9241                 return attr;
9242         }
9243
9244         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9245                 return NULL;
9246
9247         /*g_print ("got attr %s\n", method->klass->name);*/
9248
9249         sig = mono_method_signature (method);
9250         if (sig->param_count < 32) {
9251                 params = params_buf;
9252                 memset (params, 0, sizeof (void*) * sig->param_count);
9253         } else {
9254                 /* Allocate using GC so it gets GC tracking */
9255                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9256         }
9257
9258         /* skip prolog */
9259         p += 2;
9260         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9261                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9262                 if (!mono_error_ok (error))
9263                         goto fail;
9264         }
9265
9266         named = p;
9267         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9268         if (!mono_error_ok (error)) goto fail;
9269
9270         mono_runtime_try_invoke (method, attr, params, &exc, error);
9271         if (!mono_error_ok (error))
9272                 goto fail;
9273         if (exc)
9274                 goto fail;
9275
9276         num_named = read16 (named);
9277         named += 2;
9278         for (j = 0; j < num_named; j++) {
9279                 gint name_len;
9280                 char *name, named_type, data_type;
9281                 named_type = *named++;
9282                 data_type = *named++; /* type of data */
9283                 if (data_type == MONO_TYPE_SZARRAY)
9284                         data_type = *named++;
9285                 if (data_type == MONO_TYPE_ENUM) {
9286                         gint type_len;
9287                         char *type_name;
9288                         type_len = mono_metadata_decode_blob_size (named, &named);
9289                         type_name = (char *)g_malloc (type_len + 1);
9290                         memcpy (type_name, named, type_len);
9291                         type_name [type_len] = 0;
9292                         named += type_len;
9293                         /* FIXME: lookup the type and check type consistency */
9294                         g_free (type_name);
9295                 }
9296                 name_len = mono_metadata_decode_blob_size (named, &named);
9297                 name = (char *)g_malloc (name_len + 1);
9298                 memcpy (name, named, name_len);
9299                 name [name_len] = 0;
9300                 named += name_len;
9301                 if (named_type == 0x53) {
9302                         MonoClassField *field;
9303                         void *val;
9304
9305                         /* how this fail is a blackbox */
9306                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9307                         if (!field) {
9308                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9309                                 g_free (name);
9310                                 goto fail;
9311                         }
9312
9313                         val = load_cattr_value (image, field->type, named, &named, error);
9314                         if (!mono_error_ok (error)) {
9315                                 g_free (name);
9316                                 if (!type_is_reference (field->type))
9317                                         g_free (val);
9318                                 goto fail;
9319                         }
9320
9321                         mono_field_set_value (attr, field, val);
9322                         if (!type_is_reference (field->type))
9323                                 g_free (val);
9324                 } else if (named_type == 0x54) {
9325                         MonoProperty *prop;
9326                         void *pparams [1];
9327                         MonoType *prop_type;
9328
9329                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9330
9331                         if (!prop) {
9332                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9333                                 g_free (name);
9334                                 goto fail;
9335                         }
9336
9337                         if (!prop->set) {
9338                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9339                                 g_free (name);
9340                                 goto fail;
9341                         }
9342
9343                         /* can we have more that 1 arg in a custom attr named property? */
9344                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9345                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9346
9347                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9348                         if (!mono_error_ok (error)) {
9349                                 g_free (name);
9350                                 if (!type_is_reference (prop_type))
9351                                         g_free (pparams [0]);
9352                                 goto fail;
9353                         }
9354
9355
9356                         mono_property_set_value (prop, attr, pparams, NULL);
9357                         if (!type_is_reference (prop_type))
9358                                 g_free (pparams [0]);
9359                 }
9360                 g_free (name);
9361         }
9362
9363         free_param_data (method->signature, params);
9364         if (params != params_buf)
9365                 mono_gc_free_fixed (params);
9366
9367         return attr;
9368
9369 fail:
9370         free_param_data (method->signature, params);
9371         if (params != params_buf)
9372                 mono_gc_free_fixed (params);
9373         if (exc)
9374                 mono_raise_exception ((MonoException*)exc);
9375         return NULL;
9376 }
9377         
9378 /*
9379  * mono_reflection_create_custom_attr_data_args:
9380  *
9381  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9382  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9383  * NAMED_ARG_INFO will contain information about the named arguments.
9384  */
9385 void
9386 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)
9387 {
9388         MonoArray *typedargs, *namedargs;
9389         MonoClass *attrklass;
9390         MonoDomain *domain;
9391         const char *p = (const char*)data;
9392         const char *named;
9393         guint32 i, j, num_named;
9394         CattrNamedArg *arginfo = NULL;
9395
9396         *typed_args = NULL;
9397         *named_args = NULL;
9398         *named_arg_info = NULL;
9399
9400         mono_error_init (error);
9401
9402         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9403                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9404                 return;
9405         }
9406
9407         mono_class_init (method->klass);
9408         
9409         domain = mono_domain_get ();
9410
9411         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9412                 return;
9413
9414         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9415         
9416         /* skip prolog */
9417         p += 2;
9418         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9419                 MonoObject *obj;
9420                 void *val;
9421
9422                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9423                 if (!mono_error_ok (error)) {
9424                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9425                                 g_free (val);
9426                         return;
9427                 }
9428
9429                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9430                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9431                 mono_array_setref (typedargs, i, obj);
9432
9433                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9434                         g_free (val);
9435         }
9436
9437         named = p;
9438         num_named = read16 (named);
9439         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9440         named += 2;
9441         attrklass = method->klass;
9442
9443         arginfo = g_new0 (CattrNamedArg, num_named);
9444         *named_arg_info = arginfo;
9445
9446         for (j = 0; j < num_named; j++) {
9447                 gint name_len;
9448                 char *name, named_type, data_type;
9449                 named_type = *named++;
9450                 data_type = *named++; /* type of data */
9451                 if (data_type == MONO_TYPE_SZARRAY)
9452                         data_type = *named++;
9453                 if (data_type == MONO_TYPE_ENUM) {
9454                         gint type_len;
9455                         char *type_name;
9456                         type_len = mono_metadata_decode_blob_size (named, &named);
9457                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9458                                 goto fail;
9459
9460                         type_name = (char *)g_malloc (type_len + 1);
9461                         memcpy (type_name, named, type_len);
9462                         type_name [type_len] = 0;
9463                         named += type_len;
9464                         /* FIXME: lookup the type and check type consistency */
9465                         g_free (type_name);
9466                 }
9467                 name_len = mono_metadata_decode_blob_size (named, &named);
9468                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9469                         goto fail;
9470                 name = (char *)g_malloc (name_len + 1);
9471                 memcpy (name, named, name_len);
9472                 name [name_len] = 0;
9473                 named += name_len;
9474                 if (named_type == 0x53) {
9475                         MonoObject *obj;
9476                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9477                         void *val;
9478
9479                         if (!field) {
9480                                 g_free (name);
9481                                 goto fail;
9482                         }
9483
9484                         arginfo [j].type = field->type;
9485                         arginfo [j].field = field;
9486
9487                         val = load_cattr_value (image, field->type, named, &named, error);
9488                         if (!mono_error_ok (error)) {
9489                                 if (!type_is_reference (field->type))
9490                                         g_free (val);
9491                                 g_free (name);
9492                                 return;
9493                         }
9494
9495                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9496                         mono_array_setref (namedargs, j, obj);
9497                         if (!type_is_reference (field->type))
9498                                 g_free (val);
9499                 } else if (named_type == 0x54) {
9500                         MonoObject *obj;
9501                         MonoType *prop_type;
9502                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9503                         void *val;
9504
9505                         if (!prop || !prop->set) {
9506                                 g_free (name);
9507                                 goto fail;
9508                         }
9509
9510                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9511                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9512
9513                         arginfo [j].type = prop_type;
9514                         arginfo [j].prop = prop;
9515
9516                         val = load_cattr_value (image, prop_type, named, &named, error);
9517                         if (!mono_error_ok (error)) {
9518                                 if (!type_is_reference (prop_type))
9519                                         g_free (val);
9520                                 g_free (name);
9521                                 return;
9522                         }
9523
9524                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9525                         mono_array_setref (namedargs, j, obj);
9526                         if (!type_is_reference (prop_type))
9527                                 g_free (val);
9528                 }
9529                 g_free (name);
9530         }
9531
9532         *typed_args = typedargs;
9533         *named_args = namedargs;
9534         return;
9535 fail:
9536         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9537         g_free (arginfo);
9538         *named_arg_info = NULL;
9539 }
9540
9541 void
9542 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9543 {
9544         MonoDomain *domain;
9545         MonoArray *typedargs, *namedargs;
9546         MonoImage *image;
9547         MonoMethod *method;
9548         CattrNamedArg *arginfo = NULL;
9549         MonoError error;
9550         int i;
9551
9552         mono_error_init (&error);
9553
9554         *ctor_args = NULL;
9555         *named_args = NULL;
9556
9557         if (len == 0)
9558                 return;
9559
9560         image = assembly->assembly->image;
9561         method = ref_method->method;
9562         domain = mono_object_domain (ref_method);
9563
9564         if (!mono_class_init (method->klass))
9565                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9566
9567         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9568         if (!mono_error_ok (&error))
9569                 goto leave;
9570
9571         if (mono_loader_get_last_error ()) {
9572                 mono_error_set_from_loader_error (&error);
9573                 goto leave;
9574         }
9575
9576         if (!typedargs || !namedargs)
9577                 goto leave;
9578
9579         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9580                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9581                 MonoObject *typedarg;
9582
9583                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9584                 if (!is_ok (&error))
9585                         goto leave;
9586                 mono_array_setref (typedargs, i, typedarg);
9587         }
9588
9589         for (i = 0; i < mono_array_length (namedargs); ++i) {
9590                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9591                 MonoObject *typedarg, *namedarg, *minfo;
9592
9593                 if (arginfo [i].prop) {
9594                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9595                         if (!minfo)
9596                                 goto leave;
9597                 } else {
9598                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9599                         if (!mono_error_ok (&error))
9600                                 goto leave;
9601                 }
9602
9603                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9604                 if (!is_ok (&error))
9605                         goto leave;
9606                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9607                 if (!is_ok (&error))
9608                         goto leave;
9609
9610                 mono_array_setref (namedargs, i, namedarg);
9611         }
9612
9613         *ctor_args = typedargs;
9614         *named_args = namedargs;
9615 leave:
9616         g_free (arginfo);
9617         mono_error_raise_exception (&error);
9618
9619 }
9620
9621 static MonoObject*
9622 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9623 {
9624         static MonoMethod *ctor;
9625
9626         MonoDomain *domain;
9627         MonoObject *attr;
9628         void *params [4];
9629
9630         mono_error_init (error);
9631
9632         g_assert (image->assembly);
9633
9634         if (!ctor)
9635                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9636
9637         domain = mono_domain_get ();
9638         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9639         return_val_if_nok (error, NULL);
9640         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9641         return_val_if_nok (error, NULL);
9642         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9643         return_val_if_nok (error, NULL);
9644         params [2] = (gpointer)&cattr->data;
9645         params [3] = &cattr->data_size;
9646
9647         mono_runtime_invoke_checked (ctor, attr, params, error);
9648         return_val_if_nok (error, NULL);
9649         return attr;
9650 }
9651
9652 static MonoArray*
9653 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9654 {
9655         MonoArray *result;
9656         MonoObject *attr;
9657         int i, n;
9658
9659         mono_error_init (error);
9660
9661         n = 0;
9662         for (i = 0; i < cinfo->num_attrs; ++i) {
9663                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9664                         n ++;
9665         }
9666
9667         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9668         n = 0;
9669         for (i = 0; i < cinfo->num_attrs; ++i) {
9670                 if (!cinfo->attrs [i].ctor) {
9671                         /* The cattr type is not finished yet */
9672                         /* We should include the type name but cinfo doesn't contain it */
9673                         mono_error_set_type_load_name (error, NULL, NULL, "");
9674                         return NULL;
9675                 }
9676                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9677                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9678                         if (!mono_error_ok (error))
9679                                 return result;
9680                         mono_array_setref (result, n, attr);
9681                         n ++;
9682                 }
9683         }
9684         return result;
9685 }
9686
9687 MonoArray*
9688 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9689 {
9690         MonoError error;
9691         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9692         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9693
9694         return result;
9695 }
9696
9697 static MonoArray*
9698 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9699 {
9700         MonoArray *result;
9701         MonoObject *attr;
9702         int i;
9703         
9704         mono_error_init (error);
9705         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9706         for (i = 0; i < cinfo->num_attrs; ++i) {
9707                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9708                 return_val_if_nok (error, NULL);
9709                 mono_array_setref (result, i, attr);
9710         }
9711         return result;
9712 }
9713
9714 /**
9715  * mono_custom_attrs_from_index:
9716  *
9717  * Returns: NULL if no attributes are found or if a loading error occurs.
9718  */
9719 MonoCustomAttrInfo*
9720 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9721 {
9722         MonoError error;
9723         MonoCustomAttrInfo *result = mono_custom_attrs_from_index_checked (image, idx, &error);
9724         mono_error_cleanup (&error); /* FIXME a better public API that doesn't swallow the error. */
9725         return result;
9726 }
9727 /**
9728  * mono_custom_attrs_from_index_checked:
9729  *
9730  * Returns: NULL if no attributes are found.  On error returns NULL and sets @error.
9731  */
9732 MonoCustomAttrInfo*
9733 mono_custom_attrs_from_index_checked (MonoImage *image, guint32 idx, MonoError *error)
9734 {
9735         guint32 mtoken, i, len;
9736         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9737         MonoTableInfo *ca;
9738         MonoCustomAttrInfo *ainfo;
9739         GList *tmp, *list = NULL;
9740         const char *data;
9741         MonoCustomAttrEntry* attr;
9742
9743         mono_error_init (error);
9744
9745         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9746
9747         i = mono_metadata_custom_attrs_from_index (image, idx);
9748         if (!i)
9749                 return NULL;
9750         i --;
9751         while (i < ca->rows) {
9752                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9753                         break;
9754                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9755                 ++i;
9756         }
9757         len = g_list_length (list);
9758         if (!len)
9759                 return NULL;
9760         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9761         ainfo->num_attrs = len;
9762         ainfo->image = image;
9763         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9764                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9765                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9766                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9767                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9768                         mtoken |= MONO_TOKEN_METHOD_DEF;
9769                         break;
9770                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9771                         mtoken |= MONO_TOKEN_MEMBER_REF;
9772                         break;
9773                 default:
9774                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9775                         break;
9776                 }
9777                 attr = &ainfo->attrs [i - 1];
9778                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, error);
9779                 if (!attr->ctor) {
9780                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (error));
9781                         g_list_free (list);
9782                         g_free (ainfo);
9783                         return NULL;
9784                 }
9785
9786                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9787                         /*FIXME raising an exception here doesn't make any sense*/
9788                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9789                         g_list_free (list);
9790                         g_free (ainfo);
9791                         return NULL;
9792                 }
9793                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9794                 attr->data_size = mono_metadata_decode_value (data, &data);
9795                 attr->data = (guchar*)data;
9796         }
9797         g_list_free (list);
9798
9799         return ainfo;
9800 }
9801
9802 MonoCustomAttrInfo*
9803 mono_custom_attrs_from_method (MonoMethod *method)
9804 {
9805         MonoError error;
9806         MonoCustomAttrInfo* result = mono_custom_attrs_from_method_checked  (method, &error);
9807         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9808         return result;
9809 }
9810
9811 MonoCustomAttrInfo*
9812 mono_custom_attrs_from_method_checked (MonoMethod *method, MonoError *error)
9813 {
9814         guint32 idx;
9815
9816         mono_error_init (error);
9817
9818         /*
9819          * An instantiated method has the same cattrs as the generic method definition.
9820          *
9821          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9822          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9823          */
9824         if (method->is_inflated)
9825                 method = ((MonoMethodInflated *) method)->declaring;
9826         
9827         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9828                 return lookup_custom_attr (method->klass->image, method);
9829
9830         if (!method->token)
9831                 /* Synthetic methods */
9832                 return NULL;
9833
9834         idx = mono_method_get_index (method);
9835         idx <<= MONO_CUSTOM_ATTR_BITS;
9836         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9837         return mono_custom_attrs_from_index_checked (method->klass->image, idx, error);
9838 }
9839
9840 MonoCustomAttrInfo*
9841 mono_custom_attrs_from_class (MonoClass *klass)
9842 {
9843         MonoError error;
9844         MonoCustomAttrInfo *result = mono_custom_attrs_from_class_checked (klass, &error);
9845         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9846         return result;
9847 }
9848
9849 MonoCustomAttrInfo*
9850 mono_custom_attrs_from_class_checked (MonoClass *klass, MonoError *error)
9851 {
9852         guint32 idx;
9853
9854         mono_error_init (error);
9855
9856         if (klass->generic_class)
9857                 klass = klass->generic_class->container_class;
9858
9859         if (image_is_dynamic (klass->image))
9860                 return lookup_custom_attr (klass->image, klass);
9861
9862         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9863                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9864                 idx <<= MONO_CUSTOM_ATTR_BITS;
9865                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9866         } else {
9867                 idx = mono_metadata_token_index (klass->type_token);
9868                 idx <<= MONO_CUSTOM_ATTR_BITS;
9869                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9870         }
9871         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9872 }
9873
9874 MonoCustomAttrInfo*
9875 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9876 {
9877         MonoError error;
9878         MonoCustomAttrInfo *result = mono_custom_attrs_from_assembly_checked (assembly, &error);
9879         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9880         return result;
9881 }
9882
9883 MonoCustomAttrInfo*
9884 mono_custom_attrs_from_assembly_checked (MonoAssembly *assembly, MonoError *error)
9885 {
9886         guint32 idx;
9887         
9888         mono_error_init (error);
9889
9890         if (image_is_dynamic (assembly->image))
9891                 return lookup_custom_attr (assembly->image, assembly);
9892         idx = 1; /* there is only one assembly */
9893         idx <<= MONO_CUSTOM_ATTR_BITS;
9894         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9895         return mono_custom_attrs_from_index_checked (assembly->image, idx, error);
9896 }
9897
9898 static MonoCustomAttrInfo*
9899 mono_custom_attrs_from_module (MonoImage *image, MonoError *error)
9900 {
9901         guint32 idx;
9902         
9903         if (image_is_dynamic (image))
9904                 return lookup_custom_attr (image, image);
9905         idx = 1; /* there is only one module */
9906         idx <<= MONO_CUSTOM_ATTR_BITS;
9907         idx |= MONO_CUSTOM_ATTR_MODULE;
9908         return mono_custom_attrs_from_index_checked (image, idx, error);
9909 }
9910
9911 MonoCustomAttrInfo*
9912 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9913 {
9914         MonoError error;
9915         MonoCustomAttrInfo * result = mono_custom_attrs_from_property_checked (klass, property, &error);
9916         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9917         return result;
9918 }
9919
9920 MonoCustomAttrInfo*
9921 mono_custom_attrs_from_property_checked (MonoClass *klass, MonoProperty *property, MonoError *error)
9922 {
9923         guint32 idx;
9924         
9925         if (image_is_dynamic (klass->image)) {
9926                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9927                 return lookup_custom_attr (klass->image, property);
9928         }
9929         idx = find_property_index (klass, property);
9930         idx <<= MONO_CUSTOM_ATTR_BITS;
9931         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9932         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9933 }
9934
9935 MonoCustomAttrInfo*
9936 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9937 {
9938         MonoError error;
9939         MonoCustomAttrInfo * result = mono_custom_attrs_from_event_checked (klass, event, &error);
9940         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9941         return result;
9942 }
9943
9944 MonoCustomAttrInfo*
9945 mono_custom_attrs_from_event_checked (MonoClass *klass, MonoEvent *event, MonoError *error)
9946 {
9947         guint32 idx;
9948         
9949         if (image_is_dynamic (klass->image)) {
9950                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9951                 return lookup_custom_attr (klass->image, event);
9952         }
9953         idx = find_event_index (klass, event);
9954         idx <<= MONO_CUSTOM_ATTR_BITS;
9955         idx |= MONO_CUSTOM_ATTR_EVENT;
9956         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9957 }
9958
9959 MonoCustomAttrInfo*
9960 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9961 {
9962         MonoError error;
9963         MonoCustomAttrInfo * result = mono_custom_attrs_from_field_checked (klass, field, &error);
9964         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9965         return result;
9966 }
9967
9968 MonoCustomAttrInfo*
9969 mono_custom_attrs_from_field_checked (MonoClass *klass, MonoClassField *field, MonoError *error)
9970 {
9971         guint32 idx;
9972         mono_error_init (error);
9973
9974         if (image_is_dynamic (klass->image)) {
9975                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9976                 return lookup_custom_attr (klass->image, field);
9977         }
9978         idx = find_field_index (klass, field);
9979         idx <<= MONO_CUSTOM_ATTR_BITS;
9980         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9981         return mono_custom_attrs_from_index_checked (klass->image, idx, error);
9982 }
9983
9984 /**
9985  * mono_custom_attrs_from_param:
9986  * @method: handle to the method that we want to retrieve custom parameter information from
9987  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9988  *
9989  * The result must be released with mono_custom_attrs_free().
9990  *
9991  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9992  */
9993 MonoCustomAttrInfo*
9994 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9995 {
9996         MonoError error;
9997         MonoCustomAttrInfo *result = mono_custom_attrs_from_param_checked (method, param, &error);
9998         mono_error_cleanup (&error); /* FIXME want a better API that doesn't swallow the error */
9999         return result;
10000 }
10001
10002 /**
10003  * mono_custom_attrs_from_param_checked:
10004  * @method: handle to the method that we want to retrieve custom parameter information from
10005  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
10006  * @error: set on error
10007  *
10008  * The result must be released with mono_custom_attrs_free().
10009  *
10010  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.  On failure returns NULL and sets @error.
10011  */
10012 MonoCustomAttrInfo*
10013 mono_custom_attrs_from_param_checked (MonoMethod *method, guint32 param, MonoError *error)
10014 {
10015         MonoTableInfo *ca;
10016         guint32 i, idx, method_index;
10017         guint32 param_list, param_last, param_pos, found;
10018         MonoImage *image;
10019         MonoReflectionMethodAux *aux;
10020
10021         mono_error_init (error);
10022
10023         /*
10024          * An instantiated method has the same cattrs as the generic method definition.
10025          *
10026          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
10027          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
10028          */
10029         if (method->is_inflated)
10030                 method = ((MonoMethodInflated *) method)->declaring;
10031
10032         if (image_is_dynamic (method->klass->image)) {
10033                 MonoCustomAttrInfo *res, *ainfo;
10034                 int size;
10035
10036                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
10037                 if (!aux || !aux->param_cattr)
10038                         return NULL;
10039
10040                 /* Need to copy since it will be freed later */
10041                 ainfo = aux->param_cattr [param];
10042                 if (!ainfo)
10043                         return NULL;
10044                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
10045                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
10046                 memcpy (res, ainfo, size);
10047                 return res;
10048         }
10049
10050         image = method->klass->image;
10051         method_index = mono_method_get_index (method);
10052         if (!method_index)
10053                 return NULL;
10054         ca = &image->tables [MONO_TABLE_METHOD];
10055
10056         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
10057         if (method_index == ca->rows) {
10058                 ca = &image->tables [MONO_TABLE_PARAM];
10059                 param_last = ca->rows + 1;
10060         } else {
10061                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
10062                 ca = &image->tables [MONO_TABLE_PARAM];
10063         }
10064         found = FALSE;
10065         for (i = param_list; i < param_last; ++i) {
10066                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
10067                 if (param_pos == param) {
10068                         found = TRUE;
10069                         break;
10070                 }
10071         }
10072         if (!found)
10073                 return NULL;
10074         idx = i;
10075         idx <<= MONO_CUSTOM_ATTR_BITS;
10076         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
10077         return mono_custom_attrs_from_index_checked (image, idx, error);
10078 }
10079
10080 gboolean
10081 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10082 {
10083         int i;
10084         MonoClass *klass;
10085         for (i = 0; i < ainfo->num_attrs; ++i) {
10086                 klass = ainfo->attrs [i].ctor->klass;
10087                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
10088                         return TRUE;
10089         }
10090         return FALSE;
10091 }
10092
10093 MonoObject*
10094 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
10095 {
10096         MonoError error;
10097         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
10098         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
10099         return res;
10100 }
10101
10102 MonoObject*
10103 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
10104 {
10105         int i, attr_index;
10106         MonoClass *klass;
10107         MonoArray *attrs;
10108
10109         mono_error_init (error);
10110
10111         attr_index = -1;
10112         for (i = 0; i < ainfo->num_attrs; ++i) {
10113                 klass = ainfo->attrs [i].ctor->klass;
10114                 if (mono_class_has_parent (klass, attr_klass)) {
10115                         attr_index = i;
10116                         break;
10117                 }
10118         }
10119         if (attr_index == -1)
10120                 return NULL;
10121
10122         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
10123         if (!mono_error_ok (error))
10124                 return NULL;
10125         return mono_array_get (attrs, MonoObject*, attr_index);
10126 }
10127
10128 /*
10129  * mono_reflection_get_custom_attrs_info:
10130  * @obj: a reflection object handle
10131  *
10132  * Return the custom attribute info for attributes defined for the
10133  * reflection handle @obj. The objects.
10134  *
10135  * FIXME this function leaks like a sieve for SRE objects.
10136  */
10137 MonoCustomAttrInfo*
10138 mono_reflection_get_custom_attrs_info (MonoObject *obj)
10139 {
10140         MonoError error;
10141         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
10142         mono_error_assert_ok (&error);
10143         return result;
10144 }
10145
10146 /**
10147  * mono_reflection_get_custom_attrs_info_checked:
10148  * @obj: a reflection object handle
10149  * @error: set on error
10150  *
10151  * Return the custom attribute info for attributes defined for the
10152  * reflection handle @obj. The objects.
10153  *
10154  * On failure returns NULL and sets @error.
10155  *
10156  * FIXME this function leaks like a sieve for SRE objects.
10157  */
10158 MonoCustomAttrInfo*
10159 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
10160 {
10161         MonoClass *klass;
10162         MonoCustomAttrInfo *cinfo = NULL;
10163         
10164         mono_error_init (error);
10165
10166         klass = obj->vtable->klass;
10167         if (klass == mono_defaults.monotype_class) {
10168                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj, error);
10169                 return_val_if_nok (error, NULL);
10170                 klass = mono_class_from_mono_type (type);
10171                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
10172                 cinfo = mono_custom_attrs_from_class_checked (klass, error);
10173                 return_val_if_nok (error, NULL);
10174         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
10175                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
10176                 cinfo = mono_custom_attrs_from_assembly_checked (rassembly->assembly, error);
10177                 return_val_if_nok (error, NULL);
10178         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
10179                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
10180                 cinfo = mono_custom_attrs_from_module (module->image, error);
10181                 return_val_if_nok (error, NULL);
10182         } else if (strcmp ("MonoProperty", klass->name) == 0) {
10183                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
10184                 cinfo = mono_custom_attrs_from_property_checked (rprop->property->parent, rprop->property, error);
10185                 return_val_if_nok (error, NULL);
10186         } else if (strcmp ("MonoEvent", klass->name) == 0) {
10187                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
10188                 cinfo = mono_custom_attrs_from_event_checked (revent->event->parent, revent->event, error);
10189                 return_val_if_nok (error, NULL);
10190         } else if (strcmp ("MonoField", klass->name) == 0) {
10191                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
10192                 cinfo = mono_custom_attrs_from_field_checked (rfield->field->parent, rfield->field, error);
10193                 return_val_if_nok (error, NULL);
10194         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
10195                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10196                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10197                 return_val_if_nok (error, NULL);
10198         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
10199                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
10200                 cinfo = mono_custom_attrs_from_method_checked (rmethod->method, error);
10201                 return_val_if_nok (error, NULL);
10202         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
10203                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
10204                 MonoClass *member_class = mono_object_class (param->MemberImpl);
10205                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
10206                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
10207                         cinfo = mono_custom_attrs_from_param_checked (rmethod->method, param->PositionImpl + 1, error);
10208                         return_val_if_nok (error, NULL);
10209                 } else if (is_sr_mono_property (member_class)) {
10210                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
10211                         MonoMethod *method;
10212                         if (!(method = prop->property->get))
10213                                 method = prop->property->set;
10214                         g_assert (method);
10215
10216                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10217                         return_val_if_nok (error, NULL);
10218                 } 
10219 #ifndef DISABLE_REFLECTION_EMIT
10220                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
10221                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
10222                         return_val_if_nok (error, NULL);
10223                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10224                         return_val_if_nok (error, NULL);
10225                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
10226                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
10227                         MonoMethod *method = NULL;
10228                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
10229                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
10230                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
10231                                 method = ((MonoReflectionMethod *)c->cb)->method;
10232                         else
10233                                 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));
10234
10235                         cinfo = mono_custom_attrs_from_param_checked (method, param->PositionImpl + 1, error);
10236                         return_val_if_nok (error, NULL);
10237                 } 
10238 #endif
10239                 else {
10240                         char *type_name = mono_type_get_full_name (member_class);
10241                         mono_error_set_generic_error (error, "System", "NotSupportedException",
10242                                                       "Custom attributes on a ParamInfo with member %s are not supported",
10243                                                       type_name);
10244                         g_free (type_name);
10245                         return NULL;
10246                 }
10247         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
10248                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
10249                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
10250         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
10251                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
10252                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
10253         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
10254                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
10255                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
10256         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
10257                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
10258                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
10259         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
10260                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
10261                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
10262         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
10263                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
10264                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
10265         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
10266                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
10267                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
10268                 return_val_if_nok (error, NULL);
10269         } else { /* handle other types here... */
10270                 g_error ("get custom attrs not yet supported for %s", klass->name);
10271         }
10272
10273         return cinfo;
10274 }
10275
10276 /*
10277  * mono_reflection_get_custom_attrs_by_type:
10278  * @obj: a reflection object handle
10279  *
10280  * Return an array with all the custom attributes defined of the
10281  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
10282  * of that type are returned. The objects are fully build. Return NULL if a loading error
10283  * occurs.
10284  */
10285 MonoArray*
10286 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
10287 {
10288         MonoArray *result;
10289         MonoCustomAttrInfo *cinfo;
10290
10291         mono_error_init (error);
10292
10293         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10294         return_val_if_nok (error, NULL);
10295         if (cinfo) {
10296                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
10297                 if (!result)
10298                         return NULL;
10299                 if (!cinfo->cached)
10300                         mono_custom_attrs_free (cinfo);
10301         } else {
10302                 mono_loader_assert_no_error ();
10303                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
10304         }
10305
10306         return result;
10307 }
10308
10309 /*
10310  * mono_reflection_get_custom_attrs:
10311  * @obj: a reflection object handle
10312  *
10313  * Return an array with all the custom attributes defined of the
10314  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
10315  * occurs.
10316  */
10317 MonoArray*
10318 mono_reflection_get_custom_attrs (MonoObject *obj)
10319 {
10320         MonoError error;
10321
10322         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
10323 }
10324
10325 /*
10326  * mono_reflection_get_custom_attrs_data:
10327  * @obj: a reflection obj handle
10328  *
10329  * Returns an array of System.Reflection.CustomAttributeData,
10330  * which include information about attributes reflected on
10331  * types loaded using the Reflection Only methods
10332  */
10333 MonoArray*
10334 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10335 {
10336         MonoError error;
10337         MonoArray* result;
10338         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10339         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10340         return result;
10341 }
10342
10343 /*
10344  * mono_reflection_get_custom_attrs_data_checked:
10345  * @obj: a reflection obj handle
10346  * @error: set on error
10347  *
10348  * Returns an array of System.Reflection.CustomAttributeData,
10349  * which include information about attributes reflected on
10350  * types loaded using the Reflection Only methods
10351  */
10352 MonoArray*
10353 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10354 {
10355         MonoArray *result;
10356         MonoCustomAttrInfo *cinfo;
10357
10358         mono_error_init (error);
10359
10360         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10361         return_val_if_nok (error, NULL);
10362         if (cinfo) {
10363                 result = mono_custom_attrs_data_construct (cinfo, error);
10364                 return_val_if_nok (error, NULL);
10365                 if (!cinfo->cached)
10366                         mono_custom_attrs_free (cinfo);
10367         } else
10368                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10369
10370         if (mono_loader_get_last_error ())
10371                 mono_error_set_from_loader_error (error);
10372
10373         return result;
10374 }
10375
10376 static MonoReflectionType*
10377 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10378 {
10379         static MonoMethod *method_get_underlying_system_type = NULL;
10380         MonoReflectionType *rt;
10381         MonoMethod *usertype_method;
10382
10383         mono_error_init (error);
10384
10385         if (!method_get_underlying_system_type)
10386                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10387
10388         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10389
10390         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10391
10392         return rt;
10393 }
10394
10395
10396 static gboolean
10397 is_corlib_type (MonoClass *klass)
10398 {
10399         return klass->image == mono_defaults.corlib;
10400 }
10401
10402 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10403         static MonoClass *cached_class; \
10404         if (cached_class) \
10405                 return cached_class == _class; \
10406         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10407                 cached_class = _class; \
10408                 return TRUE; \
10409         } \
10410         return FALSE; \
10411 } while (0) \
10412
10413
10414 #ifndef DISABLE_REFLECTION_EMIT
10415 static gboolean
10416 is_sre_array (MonoClass *klass)
10417 {
10418         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10419 }
10420
10421 static gboolean
10422 is_sre_byref (MonoClass *klass)
10423 {
10424         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10425 }
10426
10427 static gboolean
10428 is_sre_pointer (MonoClass *klass)
10429 {
10430         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10431 }
10432
10433 static gboolean
10434 is_sre_generic_instance (MonoClass *klass)
10435 {
10436         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10437 }
10438
10439 static gboolean
10440 is_sre_type_builder (MonoClass *klass)
10441 {
10442         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10443 }
10444
10445 static gboolean
10446 is_sre_method_builder (MonoClass *klass)
10447 {
10448         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10449 }
10450
10451 static gboolean
10452 is_sre_ctor_builder (MonoClass *klass)
10453 {
10454         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10455 }
10456
10457 static gboolean
10458 is_sre_field_builder (MonoClass *klass)
10459 {
10460         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10461 }
10462
10463 static gboolean
10464 is_sre_method_on_tb_inst (MonoClass *klass)
10465 {
10466         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10467 }
10468
10469 static gboolean
10470 is_sre_ctor_on_tb_inst (MonoClass *klass)
10471 {
10472         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10473 }
10474
10475 MonoType*
10476 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
10477 {
10478         MonoClass *klass;
10479         mono_error_init (error);
10480
10481         if (!ref)
10482                 return NULL;
10483         if (ref->type)
10484                 return ref->type;
10485
10486         if (is_usertype (ref)) {
10487                 ref = mono_reflection_type_get_underlying_system_type (ref, error);
10488                 if (ref == NULL || is_usertype (ref) || !is_ok (error))
10489                         return NULL;
10490                 if (ref->type)
10491                         return ref->type;
10492         }
10493
10494         klass = mono_object_class (ref);
10495
10496         if (is_sre_array (klass)) {
10497                 MonoType *res;
10498                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10499                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type, error);
10500                 return_val_if_nok (error, NULL);
10501                 g_assert (base);
10502                 if (sre_array->rank == 0) //single dimentional array
10503                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10504                 else
10505                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10506                 sre_array->type.type = res;
10507                 return res;
10508         } else if (is_sre_byref (klass)) {
10509                 MonoType *res;
10510                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10511                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type, error);
10512                 return_val_if_nok (error, NULL);
10513                 g_assert (base);
10514                 res = &mono_class_from_mono_type (base)->this_arg;
10515                 sre_byref->type.type = res;
10516                 return res;
10517         } else if (is_sre_pointer (klass)) {
10518                 MonoType *res;
10519                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10520                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type, error);
10521                 return_val_if_nok (error, NULL);
10522                 g_assert (base);
10523                 res = &mono_ptr_class_get (base)->byval_arg;
10524                 sre_pointer->type.type = res;
10525                 return res;
10526         } else if (is_sre_generic_instance (klass)) {
10527                 MonoType *res, **types;
10528                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10529                 int i, count;
10530
10531                 count = mono_array_length (gclass->type_arguments);
10532                 types = g_new0 (MonoType*, count);
10533                 for (i = 0; i < count; ++i) {
10534                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10535                         types [i] = mono_reflection_type_get_handle (t, error);
10536                         if (!types[i] || !is_ok (error)) {
10537                                 g_free (types);
10538                                 return NULL;
10539                         }
10540                 }
10541
10542                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10543                 g_free (types);
10544                 g_assert (res);
10545                 gclass->type.type = res;
10546                 return res;
10547         }
10548
10549         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10550         return NULL;
10551 }
10552
10553 void
10554 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10555 {
10556         MonoError error;
10557         mono_reflection_type_get_handle (type, &error);
10558         mono_error_set_pending_exception (&error);
10559 }
10560
10561 void
10562 mono_reflection_register_with_runtime (MonoReflectionType *type)
10563 {
10564         MonoError error;
10565         MonoType *res = mono_reflection_type_get_handle (type, &error);
10566         mono_error_raise_exception (&error); /* FIXME don't raise here */
10567         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10568         MonoClass *klass;
10569
10570         if (!res)
10571                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10572
10573         klass = mono_class_from_mono_type (res);
10574
10575         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10576         mono_domain_lock (domain);
10577
10578         if (!image_is_dynamic (klass->image)) {
10579                 mono_class_setup_supertypes (klass);
10580         } else {
10581                 if (!domain->type_hash)
10582                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10583                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10584                 mono_g_hash_table_insert (domain->type_hash, res, type);
10585         }
10586         mono_domain_unlock (domain);
10587         mono_loader_unlock ();
10588 }
10589
10590 /**
10591  * LOCKING: Assumes the loader lock is held.
10592  */
10593 static MonoMethodSignature*
10594 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10595         MonoError error;
10596         MonoMethodSignature *sig;
10597         int count, i;
10598
10599         count = parameters? mono_array_length (parameters): 0;
10600
10601         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10602         sig->param_count = count;
10603         sig->sentinelpos = -1; /* FIXME */
10604         for (i = 0; i < count; ++i) {
10605                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, &error);
10606                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10607         }
10608         return sig;
10609 }
10610
10611 /**
10612  * LOCKING: Assumes the loader lock is held.
10613  */
10614 static MonoMethodSignature*
10615 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10616         MonoMethodSignature *sig;
10617
10618         sig = parameters_to_signature (image, ctor->parameters);
10619         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10620         sig->ret = &mono_defaults.void_class->byval_arg;
10621         return sig;
10622 }
10623
10624 /**
10625  * LOCKING: Assumes the loader lock is held.
10626  */
10627 static MonoMethodSignature*
10628 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10629         MonoError error;
10630         MonoMethodSignature *sig;
10631
10632         sig = parameters_to_signature (image, method->parameters);
10633         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10634         if (method->rtype) {
10635                 sig->ret = mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype, &error);
10636                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10637         } else {
10638                 sig->ret = &mono_defaults.void_class->byval_arg;
10639         }
10640         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10641         return sig;
10642 }
10643
10644 static MonoMethodSignature*
10645 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10646         MonoError error;
10647         MonoMethodSignature *sig;
10648
10649         sig = parameters_to_signature (NULL, method->parameters);
10650         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10651         if (method->rtype) {
10652                 sig->ret = mono_reflection_type_get_handle (method->rtype, &error);
10653                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10654         } else {
10655                 sig->ret = &mono_defaults.void_class->byval_arg;
10656         }
10657         sig->generic_param_count = 0;
10658         return sig;
10659 }
10660
10661 static void
10662 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10663 {
10664         MonoError error;
10665         MonoClass *klass = mono_object_class (prop);
10666         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10667                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10668                 *name = mono_string_to_utf8 (pb->name);
10669                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, &error);
10670                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10671         } else {
10672                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10673                 *name = g_strdup (p->property->name);
10674                 if (p->property->get)
10675                         *type = mono_method_signature (p->property->get)->ret;
10676                 else
10677                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10678         }
10679 }
10680
10681 static void
10682 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10683 {
10684         MonoError error;
10685         MonoClass *klass = mono_object_class (field);
10686         if (strcmp (klass->name, "FieldBuilder") == 0) {
10687                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10688                 *name = mono_string_to_utf8 (fb->name);
10689                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
10690                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10691         } else {
10692                 MonoReflectionField *f = (MonoReflectionField *)field;
10693                 *name = g_strdup (mono_field_get_name (f->field));
10694                 *type = f->field->type;
10695         }
10696 }
10697
10698 #else /* DISABLE_REFLECTION_EMIT */
10699
10700 void
10701 mono_reflection_register_with_runtime (MonoReflectionType *type)
10702 {
10703         /* This is empty */
10704 }
10705
10706 static gboolean
10707 is_sre_type_builder (MonoClass *klass)
10708 {
10709         return FALSE;
10710 }
10711
10712 static gboolean
10713 is_sre_generic_instance (MonoClass *klass)
10714 {
10715         return FALSE;
10716 }
10717
10718 static void
10719 init_type_builder_generics (MonoObject *type)
10720 {
10721 }
10722
10723 #endif /* !DISABLE_REFLECTION_EMIT */
10724
10725
10726 static gboolean
10727 is_sr_mono_field (MonoClass *klass)
10728 {
10729         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10730 }
10731
10732 static gboolean
10733 is_sr_mono_property (MonoClass *klass)
10734 {
10735         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10736 }
10737
10738 static gboolean
10739 is_sr_mono_method (MonoClass *klass)
10740 {
10741         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10742 }
10743
10744 static gboolean
10745 is_sr_mono_cmethod (MonoClass *klass)
10746 {
10747         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10748 }
10749
10750 static gboolean
10751 is_sr_mono_generic_method (MonoClass *klass)
10752 {
10753         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10754 }
10755
10756 static gboolean
10757 is_sr_mono_generic_cmethod (MonoClass *klass)
10758 {
10759         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10760 }
10761
10762 gboolean
10763 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10764 {
10765         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10766 }
10767
10768 static gboolean
10769 is_usertype (MonoReflectionType *ref)
10770 {
10771         MonoClass *klass = mono_object_class (ref);
10772         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10773 }
10774
10775 static MonoReflectionType*
10776 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10777 {
10778         mono_error_init (error);
10779         if (!type || type->type)
10780                 return type;
10781
10782         if (is_usertype (type)) {
10783                 type = mono_reflection_type_get_underlying_system_type (type, error);
10784                 return_val_if_nok (error, NULL);
10785                 if (is_usertype (type)) {
10786                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10787                         return NULL;
10788                 }
10789         }
10790
10791         return type;
10792 }
10793 /*
10794  * Encode a value in a custom attribute stream of bytes.
10795  * The value to encode is either supplied as an object in argument val
10796  * (valuetypes are boxed), or as a pointer to the data in the
10797  * argument argval.
10798  * @type represents the type of the value
10799  * @buffer is the start of the buffer
10800  * @p the current position in the buffer
10801  * @buflen contains the size of the buffer and is used to return the new buffer size
10802  * if this needs to be realloced.
10803  * @retbuffer and @retp return the start and the position of the buffer
10804  */
10805 static void
10806 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10807 {
10808         MonoError error;
10809         MonoTypeEnum simple_type;
10810         
10811         if ((p-buffer) + 10 >= *buflen) {
10812                 char *newbuf;
10813                 *buflen *= 2;
10814                 newbuf = (char *)g_realloc (buffer, *buflen);
10815                 p = newbuf + (p-buffer);
10816                 buffer = newbuf;
10817         }
10818         if (!argval)
10819                 argval = ((char*)arg + sizeof (MonoObject));
10820         simple_type = type->type;
10821 handle_enum:
10822         switch (simple_type) {
10823         case MONO_TYPE_BOOLEAN:
10824         case MONO_TYPE_U1:
10825         case MONO_TYPE_I1:
10826                 *p++ = *argval;
10827                 break;
10828         case MONO_TYPE_CHAR:
10829         case MONO_TYPE_U2:
10830         case MONO_TYPE_I2:
10831                 swap_with_size (p, argval, 2, 1);
10832                 p += 2;
10833                 break;
10834         case MONO_TYPE_U4:
10835         case MONO_TYPE_I4:
10836         case MONO_TYPE_R4:
10837                 swap_with_size (p, argval, 4, 1);
10838                 p += 4;
10839                 break;
10840         case MONO_TYPE_R8:
10841                 swap_with_size (p, argval, 8, 1);
10842                 p += 8;
10843                 break;
10844         case MONO_TYPE_U8:
10845         case MONO_TYPE_I8:
10846                 swap_with_size (p, argval, 8, 1);
10847                 p += 8;
10848                 break;
10849         case MONO_TYPE_VALUETYPE:
10850                 if (type->data.klass->enumtype) {
10851                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10852                         goto handle_enum;
10853                 } else {
10854                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10855                 }
10856                 break;
10857         case MONO_TYPE_STRING: {
10858                 char *str;
10859                 guint32 slen;
10860                 if (!arg) {
10861                         *p++ = 0xFF;
10862                         break;
10863                 }
10864                 str = mono_string_to_utf8 ((MonoString*)arg);
10865                 slen = strlen (str);
10866                 if ((p-buffer) + 10 + slen >= *buflen) {
10867                         char *newbuf;
10868                         *buflen *= 2;
10869                         *buflen += slen;
10870                         newbuf = (char *)g_realloc (buffer, *buflen);
10871                         p = newbuf + (p-buffer);
10872                         buffer = newbuf;
10873                 }
10874                 mono_metadata_encode_value (slen, p, &p);
10875                 memcpy (p, str, slen);
10876                 p += slen;
10877                 g_free (str);
10878                 break;
10879         }
10880         case MONO_TYPE_CLASS: {
10881                 char *str;
10882                 guint32 slen;
10883                 MonoType *arg_type;
10884                 if (!arg) {
10885                         *p++ = 0xFF;
10886                         break;
10887                 }
10888 handle_type:
10889                 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, &error);
10890                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10891                 str = type_get_qualified_name (arg_type, NULL);
10892                 slen = strlen (str);
10893                 if ((p-buffer) + 10 + slen >= *buflen) {
10894                         char *newbuf;
10895                         *buflen *= 2;
10896                         *buflen += slen;
10897                         newbuf = (char *)g_realloc (buffer, *buflen);
10898                         p = newbuf + (p-buffer);
10899                         buffer = newbuf;
10900                 }
10901                 mono_metadata_encode_value (slen, p, &p);
10902                 memcpy (p, str, slen);
10903                 p += slen;
10904                 g_free (str);
10905                 break;
10906         }
10907         case MONO_TYPE_SZARRAY: {
10908                 int len, i;
10909                 MonoClass *eclass, *arg_eclass;
10910
10911                 if (!arg) {
10912                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10913                         break;
10914                 }
10915                 len = mono_array_length ((MonoArray*)arg);
10916                 *p++ = len & 0xff;
10917                 *p++ = (len >> 8) & 0xff;
10918                 *p++ = (len >> 16) & 0xff;
10919                 *p++ = (len >> 24) & 0xff;
10920                 *retp = p;
10921                 *retbuffer = buffer;
10922                 eclass = type->data.klass;
10923                 arg_eclass = mono_object_class (arg)->element_class;
10924
10925                 if (!eclass) {
10926                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10927                         eclass = mono_defaults.object_class;
10928                 }
10929                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10930                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10931                         int elsize = mono_class_array_element_size (arg_eclass);
10932                         for (i = 0; i < len; ++i) {
10933                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10934                                 elptr += elsize;
10935                         }
10936                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10937                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10938                         int elsize = mono_class_array_element_size (eclass);
10939                         for (i = 0; i < len; ++i) {
10940                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10941                                 elptr += elsize;
10942                         }
10943                 } else {
10944                         for (i = 0; i < len; ++i) {
10945                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10946                         }
10947                 }
10948                 break;
10949         }
10950         case MONO_TYPE_OBJECT: {
10951                 MonoClass *klass;
10952                 char *str;
10953                 guint32 slen;
10954
10955                 /*
10956                  * The parameter type is 'object' but the type of the actual
10957                  * argument is not. So we have to add type information to the blob
10958                  * too. This is completely undocumented in the spec.
10959                  */
10960
10961                 if (arg == NULL) {
10962                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10963                         *p++ = 0xFF;
10964                         break;
10965                 }
10966                 
10967                 klass = mono_object_class (arg);
10968
10969                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10970                         *p++ = 0x50;
10971                         goto handle_type;
10972                 } else if (klass->enumtype) {
10973                         *p++ = 0x55;
10974                 } else if (klass == mono_defaults.string_class) {
10975                         simple_type = MONO_TYPE_STRING;
10976                         *p++ = 0x0E;
10977                         goto handle_enum;
10978                 } else if (klass->rank == 1) {
10979                         *p++ = 0x1D;
10980                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10981                                 /* See Partition II, Appendix B3 */
10982                                 *p++ = 0x51;
10983                         else
10984                                 *p++ = klass->element_class->byval_arg.type;
10985                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10986                         break;
10987                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10988                         *p++ = simple_type = klass->byval_arg.type;
10989                         goto handle_enum;
10990                 } else {
10991                         g_error ("unhandled type in custom attr");
10992                 }
10993                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10994                 slen = strlen (str);
10995                 if ((p-buffer) + 10 + slen >= *buflen) {
10996                         char *newbuf;
10997                         *buflen *= 2;
10998                         *buflen += slen;
10999                         newbuf = (char *)g_realloc (buffer, *buflen);
11000                         p = newbuf + (p-buffer);
11001                         buffer = newbuf;
11002                 }
11003                 mono_metadata_encode_value (slen, p, &p);
11004                 memcpy (p, str, slen);
11005                 p += slen;
11006                 g_free (str);
11007                 simple_type = mono_class_enum_basetype (klass)->type;
11008                 goto handle_enum;
11009         }
11010         default:
11011                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
11012         }
11013         *retp = p;
11014         *retbuffer = buffer;
11015 }
11016
11017 static void
11018 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
11019 {
11020         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11021                 char *str = type_get_qualified_name (type, NULL);
11022                 int slen = strlen (str);
11023
11024                 *p++ = 0x55;
11025                 /*
11026                  * This seems to be optional...
11027                  * *p++ = 0x80;
11028                  */
11029                 mono_metadata_encode_value (slen, p, &p);
11030                 memcpy (p, str, slen);
11031                 p += slen;
11032                 g_free (str);
11033         } else if (type->type == MONO_TYPE_OBJECT) {
11034                 *p++ = 0x51;
11035         } else if (type->type == MONO_TYPE_CLASS) {
11036                 /* it should be a type: encode_cattr_value () has the check */
11037                 *p++ = 0x50;
11038         } else {
11039                 mono_metadata_encode_value (type->type, p, &p);
11040                 if (type->type == MONO_TYPE_SZARRAY)
11041                         /* See the examples in Partition VI, Annex B */
11042                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
11043         }
11044
11045         *retp = p;
11046 }
11047
11048 #ifndef DISABLE_REFLECTION_EMIT
11049 static void
11050 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
11051 {
11052         int len;
11053         /* Preallocate a large enough buffer */
11054         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
11055                 char *str = type_get_qualified_name (type, NULL);
11056                 len = strlen (str);
11057                 g_free (str);
11058         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
11059                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
11060                 len = strlen (str);
11061                 g_free (str);
11062         } else {
11063                 len = 0;
11064         }
11065         len += strlen (name);
11066
11067         if ((p-buffer) + 20 + len >= *buflen) {
11068                 char *newbuf;
11069                 *buflen *= 2;
11070                 *buflen += len;
11071                 newbuf = (char *)g_realloc (buffer, *buflen);
11072                 p = newbuf + (p-buffer);
11073                 buffer = newbuf;
11074         }
11075
11076         encode_field_or_prop_type (type, p, &p);
11077
11078         len = strlen (name);
11079         mono_metadata_encode_value (len, p, &p);
11080         memcpy (p, name, len);
11081         p += len;
11082         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
11083         *retp = p;
11084         *retbuffer = buffer;
11085 }
11086
11087 /*
11088  * mono_reflection_get_custom_attrs_blob:
11089  * @ctor: custom attribute constructor
11090  * @ctorArgs: arguments o the constructor
11091  * @properties:
11092  * @propValues:
11093  * @fields:
11094  * @fieldValues:
11095  * 
11096  * Creates the blob of data that needs to be saved in the metadata and that represents
11097  * the custom attributed described by @ctor, @ctorArgs etc.
11098  * Returns: a Byte array representing the blob of data.
11099  */
11100 MonoArray*
11101 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
11102 {
11103         MonoArray *result;
11104         MonoMethodSignature *sig;
11105         MonoObject *arg;
11106         char *buffer, *p;
11107         guint32 buflen, i;
11108
11109         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
11110                 /* sig is freed later so allocate it in the heap */
11111                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
11112         } else {
11113                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
11114         }
11115
11116         g_assert (mono_array_length (ctorArgs) == sig->param_count);
11117         buflen = 256;
11118         p = buffer = (char *)g_malloc (buflen);
11119         /* write the prolog */
11120         *p++ = 1;
11121         *p++ = 0;
11122         for (i = 0; i < sig->param_count; ++i) {
11123                 arg = mono_array_get (ctorArgs, MonoObject*, i);
11124                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
11125         }
11126         i = 0;
11127         if (properties)
11128                 i += mono_array_length (properties);
11129         if (fields)
11130                 i += mono_array_length (fields);
11131         *p++ = i & 0xff;
11132         *p++ = (i >> 8) & 0xff;
11133         if (properties) {
11134                 MonoObject *prop;
11135                 for (i = 0; i < mono_array_length (properties); ++i) {
11136                         MonoType *ptype;
11137                         char *pname;
11138
11139                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
11140                         get_prop_name_and_type (prop, &pname, &ptype);
11141                         *p++ = 0x54; /* PROPERTY signature */
11142                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
11143                         g_free (pname);
11144                 }
11145         }
11146
11147         if (fields) {
11148                 MonoObject *field;
11149                 for (i = 0; i < mono_array_length (fields); ++i) {
11150                         MonoType *ftype;
11151                         char *fname;
11152
11153                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
11154                         get_field_name_and_type (field, &fname, &ftype);
11155                         *p++ = 0x53; /* FIELD signature */
11156                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
11157                         g_free (fname);
11158                 }
11159         }
11160
11161         g_assert (p - buffer <= buflen);
11162         buflen = p - buffer;
11163         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11164         p = mono_array_addr (result, char, 0);
11165         memcpy (p, buffer, buflen);
11166         g_free (buffer);
11167         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
11168                 g_free (sig);
11169         return result;
11170 }
11171
11172 /*
11173  * mono_reflection_setup_internal_class:
11174  * @tb: a TypeBuilder object
11175  *
11176  * Creates a MonoClass that represents the TypeBuilder.
11177  * This is a trick that lets us simplify a lot of reflection code
11178  * (and will allow us to support Build and Run assemblies easier).
11179  */
11180 void
11181 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11182 {
11183         MonoError error;
11184         MonoClass *klass, *parent;
11185
11186         RESOLVE_TYPE (tb->parent, &error);
11187         mono_error_raise_exception (&error); /* FIXME don't raise here */
11188
11189         mono_loader_lock ();
11190
11191         if (tb->parent) {
11192                 MonoType *parent_type = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent, &error);
11193                 if (!is_ok (&error)) {
11194                         mono_loader_unlock ();
11195                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11196                 }
11197                 /* check so we can compile corlib correctly */
11198                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
11199                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
11200                         parent = parent_type->data.klass;
11201                 } else {
11202                         parent = mono_class_from_mono_type (parent_type);
11203                 }
11204         } else {
11205                 parent = NULL;
11206         }
11207         
11208         /* the type has already being created: it means we just have to change the parent */
11209         if (tb->type.type) {
11210                 klass = mono_class_from_mono_type (tb->type.type);
11211                 klass->parent = NULL;
11212                 /* fool mono_class_setup_parent */
11213                 klass->supertypes = NULL;
11214                 mono_class_setup_parent (klass, parent);
11215                 mono_class_setup_mono_type (klass);
11216                 mono_loader_unlock ();
11217                 return;
11218         }
11219
11220         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
11221
11222         klass->image = &tb->module->dynamic_image->image;
11223
11224         klass->inited = 1; /* we lie to the runtime */
11225         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
11226         if (!mono_error_ok (&error))
11227                 goto failure;
11228         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
11229         if (!mono_error_ok (&error))
11230                 goto failure;
11231         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
11232         klass->flags = tb->attrs;
11233         
11234         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
11235
11236         klass->element_class = klass;
11237
11238         if (mono_class_get_ref_info (klass) == NULL) {
11239
11240                 mono_class_set_ref_info (klass, tb);
11241
11242                 /* Put into cache so mono_class_get_checked () will find it.
11243                 Skip nested types as those should not be available on the global scope. */
11244                 if (!tb->nesting_type)
11245                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
11246
11247                 /*
11248                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
11249                 by performing a mono_class_get which does the full resolution.
11250
11251                 Working around this semantics would require us to write a lot of code for no clear advantage.
11252                 */
11253                 mono_image_append_class_to_reflection_info_set (klass);
11254         } else {
11255                 g_assert (mono_class_get_ref_info (klass) == tb);
11256         }
11257
11258         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
11259
11260         if (parent != NULL) {
11261                 mono_class_setup_parent (klass, parent);
11262         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
11263                 const char *old_n = klass->name;
11264                 /* trick to get relative numbering right when compiling corlib */
11265                 klass->name = "BuildingObject";
11266                 mono_class_setup_parent (klass, mono_defaults.object_class);
11267                 klass->name = old_n;
11268         }
11269
11270         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
11271                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
11272                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
11273                 klass->instance_size = sizeof (MonoObject);
11274                 klass->size_inited = 1;
11275                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11276         }
11277
11278         mono_class_setup_mono_type (klass);
11279
11280         mono_class_setup_supertypes (klass);
11281
11282         /*
11283          * FIXME: handle interfaces.
11284          */
11285
11286         tb->type.type = &klass->byval_arg;
11287
11288         if (tb->nesting_type) {
11289                 g_assert (tb->nesting_type->type);
11290                 MonoType *nesting_type = mono_reflection_type_get_handle (tb->nesting_type, &error);
11291                 if (!is_ok (&error)) goto failure;
11292                 klass->nested_in = mono_class_from_mono_type (nesting_type);
11293         }
11294
11295         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
11296
11297         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
11298         
11299         mono_loader_unlock ();
11300         return;
11301
11302 failure:
11303         mono_loader_unlock ();
11304         mono_error_raise_exception (&error);
11305 }
11306
11307 /*
11308  * mono_reflection_setup_generic_class:
11309  * @tb: a TypeBuilder object
11310  *
11311  * Setup the generic class before adding the first generic parameter.
11312  */
11313 void
11314 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11315 {
11316 }
11317
11318 /*
11319  * mono_reflection_create_generic_class:
11320  * @tb: a TypeBuilder object
11321  *
11322  * Creates the generic class after all generic parameters have been added.
11323  */
11324 void
11325 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11326 {
11327         MonoError error;
11328         MonoClass *klass;
11329         int count, i;
11330
11331         klass = mono_class_from_mono_type (tb->type.type);
11332
11333         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
11334
11335         if (klass->generic_container || (count == 0))
11336                 return;
11337
11338         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
11339
11340         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11341
11342         klass->generic_container->owner.klass = klass;
11343         klass->generic_container->type_argc = count;
11344         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
11345
11346         klass->is_generic = 1;
11347
11348         for (i = 0; i < count; i++) {
11349                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
11350                 MonoType *param_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, &error);
11351                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11352                 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
11353                 klass->generic_container->type_params [i] = *param;
11354                 /*Make sure we are a diferent type instance */
11355                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
11356                 klass->generic_container->type_params [i].info.pklass = NULL;
11357                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
11358
11359                 g_assert (klass->generic_container->type_params [i].param.owner);
11360         }
11361
11362         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
11363 }
11364
11365 /*
11366  * mono_reflection_create_internal_class:
11367  * @tb: a TypeBuilder object
11368  *
11369  * Actually create the MonoClass that is associated with the TypeBuilder.
11370  */
11371 void
11372 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11373 {
11374         MonoError error;
11375         MonoClass *klass;
11376
11377         klass = mono_class_from_mono_type (tb->type.type);
11378
11379         mono_loader_lock ();
11380         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11381                 MonoReflectionFieldBuilder *fb;
11382                 MonoClass *ec;
11383                 MonoType *enum_basetype;
11384
11385                 g_assert (tb->fields != NULL);
11386                 g_assert (mono_array_length (tb->fields) >= 1);
11387
11388                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11389
11390                 MonoType *field_type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11391                 if (!is_ok (&error)) {
11392                         mono_loader_unlock ();
11393                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11394                 }
11395                 if (!mono_type_is_valid_enum_basetype (field_type)) {
11396                         mono_loader_unlock ();
11397                         return;
11398                 }
11399
11400                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11401                 if (!is_ok (&error)) {
11402                         mono_loader_unlock ();
11403                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11404                 }
11405                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11406                 if (!klass->element_class)
11407                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11408
11409                 /*
11410                  * get the element_class from the current corlib.
11411                  */
11412                 ec = default_class_from_mono_type (enum_basetype);
11413                 klass->instance_size = ec->instance_size;
11414                 klass->size_inited = 1;
11415                 /* 
11416                  * this is almost safe to do with enums and it's needed to be able
11417                  * to create objects of the enum type (for use in SetConstant).
11418                  */
11419                 /* FIXME: Does this mean enums can't have method overrides ? */
11420                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11421         }
11422         mono_loader_unlock ();
11423 }
11424
11425 static MonoMarshalSpec*
11426 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11427                                                                 MonoReflectionMarshal *minfo)
11428 {
11429         MonoError error;
11430         MonoMarshalSpec *res;
11431
11432         res = image_g_new0 (image, MonoMarshalSpec, 1);
11433         res->native = (MonoMarshalNative)minfo->type;
11434
11435         switch (minfo->type) {
11436         case MONO_NATIVE_LPARRAY:
11437                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11438                 if (minfo->has_size) {
11439                         res->data.array_data.param_num = minfo->param_num;
11440                         res->data.array_data.num_elem = minfo->count;
11441                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11442                 }
11443                 else {
11444                         res->data.array_data.param_num = -1;
11445                         res->data.array_data.num_elem = -1;
11446                         res->data.array_data.elem_mult = -1;
11447                 }
11448                 break;
11449
11450         case MONO_NATIVE_BYVALTSTR:
11451         case MONO_NATIVE_BYVALARRAY:
11452                 res->data.array_data.num_elem = minfo->count;
11453                 break;
11454
11455         case MONO_NATIVE_CUSTOM:
11456                 if (minfo->marshaltyperef) {
11457                         MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, &error);
11458                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11459                         res->data.custom_data.custom_name =
11460                                 type_get_fully_qualified_name (marshaltyperef);
11461                 }
11462                 if (minfo->mcookie)
11463                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11464                 break;
11465
11466         default:
11467                 break;
11468         }
11469
11470         return res;
11471 }
11472 #endif /* !DISABLE_REFLECTION_EMIT */
11473
11474 MonoReflectionMarshalAsAttribute*
11475 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11476                                                         MonoMarshalSpec *spec, MonoError *error)
11477 {
11478         MonoReflectionType *rt;
11479         MonoReflectionMarshalAsAttribute *minfo;
11480         MonoType *mtype;
11481
11482         mono_error_init (error);
11483         
11484         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11485         if (!minfo)
11486                 return NULL;
11487         minfo->utype = spec->native;
11488
11489         switch (minfo->utype) {
11490         case MONO_NATIVE_LPARRAY:
11491                 minfo->array_subtype = spec->data.array_data.elem_type;
11492                 minfo->size_const = spec->data.array_data.num_elem;
11493                 if (spec->data.array_data.param_num != -1)
11494                         minfo->size_param_index = spec->data.array_data.param_num;
11495                 break;
11496
11497         case MONO_NATIVE_BYVALTSTR:
11498         case MONO_NATIVE_BYVALARRAY:
11499                 minfo->size_const = spec->data.array_data.num_elem;
11500                 break;
11501
11502         case MONO_NATIVE_CUSTOM:
11503                 if (spec->data.custom_data.custom_name) {
11504                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11505                         if (mtype) {
11506                                 rt = mono_type_get_object_checked (domain, mtype, error);
11507                                 if (!rt)
11508                                         return NULL;
11509
11510                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11511                         }
11512
11513                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11514                 }
11515                 if (spec->data.custom_data.cookie)
11516                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11517                 break;
11518
11519         default:
11520                 break;
11521         }
11522
11523         return minfo;
11524 }
11525
11526 #ifndef DISABLE_REFLECTION_EMIT
11527 static MonoMethod*
11528 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11529                                          ReflectionMethodBuilder *rmb,
11530                                          MonoMethodSignature *sig)
11531 {
11532         MonoError error;
11533         MonoMethod *m;
11534         MonoMethodWrapper *wrapperm;
11535         MonoMarshalSpec **specs;
11536         MonoReflectionMethodAux *method_aux;
11537         MonoImage *image;
11538         gboolean dynamic;
11539         int i;
11540
11541         mono_error_init (&error);
11542         /*
11543          * Methods created using a MethodBuilder should have their memory allocated
11544          * inside the image mempool, while dynamic methods should have their memory
11545          * malloc'd.
11546          */
11547         dynamic = rmb->refs != NULL;
11548         image = dynamic ? NULL : klass->image;
11549
11550         if (!dynamic)
11551                 g_assert (!klass->generic_class);
11552
11553         mono_loader_lock ();
11554
11555         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11556                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11557                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11558         else
11559                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11560
11561         wrapperm = (MonoMethodWrapper*)m;
11562
11563         m->dynamic = dynamic;
11564         m->slot = -1;
11565         m->flags = rmb->attrs;
11566         m->iflags = rmb->iattrs;
11567         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11568         m->klass = klass;
11569         m->signature = sig;
11570         m->sre_method = TRUE;
11571         m->skip_visibility = rmb->skip_visibility;
11572         if (rmb->table_idx)
11573                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11574
11575         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11576                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11577                         m->string_ctor = 1;
11578
11579                 m->signature->pinvoke = 1;
11580         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11581                 m->signature->pinvoke = 1;
11582
11583                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11584
11585                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11586                 g_assert (mono_error_ok (&error));
11587                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11588                 g_assert (mono_error_ok (&error));
11589                 
11590                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11591
11592                 if (image_is_dynamic (klass->image))
11593                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11594
11595                 mono_loader_unlock ();
11596
11597                 return m;
11598         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11599                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11600                 MonoMethodHeader *header;
11601                 guint32 code_size;
11602                 gint32 max_stack, i;
11603                 gint32 num_locals = 0;
11604                 gint32 num_clauses = 0;
11605                 guint8 *code;
11606
11607                 if (rmb->ilgen) {
11608                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11609                         code_size = rmb->ilgen->code_len;
11610                         max_stack = rmb->ilgen->max_stack;
11611                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11612                         if (rmb->ilgen->ex_handlers)
11613                                 num_clauses = method_count_clauses (rmb->ilgen);
11614                 } else {
11615                         if (rmb->code) {
11616                                 code = mono_array_addr (rmb->code, guint8, 0);
11617                                 code_size = mono_array_length (rmb->code);
11618                                 /* we probably need to run a verifier on the code... */
11619                                 max_stack = 8; 
11620                         }
11621                         else {
11622                                 code = NULL;
11623                                 code_size = 0;
11624                                 max_stack = 8;
11625                         }
11626                 }
11627
11628                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11629                 header->code_size = code_size;
11630                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11631                 memcpy ((char*)header->code, code, code_size);
11632                 header->max_stack = max_stack;
11633                 header->init_locals = rmb->init_locals;
11634                 header->num_locals = num_locals;
11635
11636                 for (i = 0; i < num_locals; ++i) {
11637                         MonoReflectionLocalBuilder *lb = 
11638                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11639
11640                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11641                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, &error);
11642                         mono_error_assert_ok (&error);
11643                         memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
11644                 }
11645
11646                 header->num_clauses = num_clauses;
11647                 if (num_clauses) {
11648                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11649                                                                  rmb->ilgen, num_clauses, &error);
11650                         mono_error_assert_ok (&error);
11651                 }
11652
11653                 wrapperm->header = header;
11654         }
11655
11656         if (rmb->generic_params) {
11657                 int count = mono_array_length (rmb->generic_params);
11658                 MonoGenericContainer *container = rmb->generic_container;
11659
11660                 g_assert (container);
11661
11662                 container->type_argc = count;
11663                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11664                 container->owner.method = m;
11665                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11666
11667                 m->is_generic = TRUE;
11668                 mono_method_set_generic_container (m, container);
11669
11670                 for (i = 0; i < count; i++) {
11671                         MonoReflectionGenericParam *gp =
11672                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11673                         MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, &error);
11674                         mono_error_assert_ok (&error);
11675                         MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
11676                         container->type_params [i] = *param;
11677                 }
11678
11679                 /*
11680                  * The method signature might have pointers to generic parameters that belong to other methods.
11681                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11682                  * generic parameters.
11683                  */
11684                 for (i = 0; i < m->signature->param_count; ++i) {
11685                         MonoType *t = m->signature->params [i];
11686                         if (t->type == MONO_TYPE_MVAR) {
11687                                 MonoGenericParam *gparam =  t->data.generic_param;
11688                                 if (gparam->num < count) {
11689                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11690                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11691                                 }
11692
11693                         }
11694                 }
11695
11696                 if (klass->generic_container) {
11697                         container->parent = klass->generic_container;
11698                         container->context.class_inst = klass->generic_container->context.class_inst;
11699                 }
11700                 container->context.method_inst = mono_get_shared_generic_inst (container);
11701         }
11702
11703         if (rmb->refs) {
11704                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11705                 int i;
11706                 void **data;
11707
11708                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11709
11710                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11711                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11712                 for (i = 0; i < rmb->nrefs; ++i)
11713                         data [i + 1] = rmb->refs [i];
11714         }
11715
11716         method_aux = NULL;
11717
11718         /* Parameter info */
11719         if (rmb->pinfo) {
11720                 if (!method_aux)
11721                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11722                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11723                 for (i = 0; i <= m->signature->param_count; ++i) {
11724                         MonoReflectionParamBuilder *pb;
11725                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11726                                 if ((i > 0) && (pb->attrs)) {
11727                                         /* Make a copy since it might point to a shared type structure */
11728                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11729                                         m->signature->params [i - 1]->attrs = pb->attrs;
11730                                 }
11731
11732                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11733                                         MonoDynamicImage *assembly;
11734                                         guint32 idx, len;
11735                                         MonoTypeEnum def_type;
11736                                         char *p;
11737                                         const char *p2;
11738
11739                                         if (!method_aux->param_defaults) {
11740                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11741                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11742                                         }
11743                                         assembly = (MonoDynamicImage*)klass->image;
11744                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11745                                         /* Copy the data from the blob since it might get realloc-ed */
11746                                         p = assembly->blob.data + idx;
11747                                         len = mono_metadata_decode_blob_size (p, &p2);
11748                                         len += p2 - p;
11749                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11750                                         method_aux->param_default_types [i] = def_type;
11751                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11752                                 }
11753
11754                                 if (pb->name) {
11755                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11756                                         g_assert (mono_error_ok (&error));
11757                                 }
11758                                 if (pb->cattrs) {
11759                                         if (!method_aux->param_cattr)
11760                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11761                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11762                                 }
11763                         }
11764                 }
11765         }
11766
11767         /* Parameter marshalling */
11768         specs = NULL;
11769         if (rmb->pinfo)         
11770                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11771                         MonoReflectionParamBuilder *pb;
11772                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11773                                 if (pb->marshal_info) {
11774                                         if (specs == NULL)
11775                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11776                                         specs [pb->position] = 
11777                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11778                                 }
11779                         }
11780                 }
11781         if (specs != NULL) {
11782                 if (!method_aux)
11783                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11784                 method_aux->param_marshall = specs;
11785         }
11786
11787         if (image_is_dynamic (klass->image) && method_aux)
11788                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11789
11790         mono_loader_unlock ();
11791
11792         return m;
11793 }       
11794
11795 static MonoMethod*
11796 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11797 {
11798         ReflectionMethodBuilder rmb;
11799         MonoMethodSignature *sig;
11800
11801         mono_loader_lock ();
11802         sig = ctor_builder_to_signature (klass->image, mb);
11803         mono_loader_unlock ();
11804
11805         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11806                 return NULL;
11807
11808         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11809         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11810
11811         /* If we are in a generic class, we might be called multiple times from inflate_method */
11812         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11813                 /* ilgen is no longer needed */
11814                 mb->ilgen = NULL;
11815         }
11816
11817         return mb->mhandle;
11818 }
11819
11820 static MonoMethod*
11821 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11822 {
11823         ReflectionMethodBuilder rmb;
11824         MonoMethodSignature *sig;
11825
11826         mono_error_init (error);
11827
11828         mono_loader_lock ();
11829         sig = method_builder_to_signature (klass->image, mb);
11830         mono_loader_unlock ();
11831
11832         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11833                 return NULL;
11834
11835         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11836         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11837
11838         /* If we are in a generic class, we might be called multiple times from inflate_method */
11839         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11840                 /* ilgen is no longer needed */
11841                 mb->ilgen = NULL;
11842         }
11843         return mb->mhandle;
11844 }
11845
11846 static MonoClassField*
11847 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11848 {
11849         MonoClassField *field;
11850         MonoType *custom;
11851         MonoError error;
11852
11853         field = g_new0 (MonoClassField, 1);
11854
11855         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11856         g_assert (mono_error_ok (&error));
11857         if (fb->attrs || fb->modreq || fb->modopt) {
11858                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11859                 if (!is_ok (&error)) {
11860                         g_free (field);
11861                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11862                 }
11863                 field->type = mono_metadata_type_dup (NULL, type);
11864                 field->type->attrs = fb->attrs;
11865
11866                 g_assert (image_is_dynamic (klass->image));
11867                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, &error);
11868                 g_free (field->type);
11869                 if (!is_ok (&error)) {
11870                         g_free (field);
11871                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11872                 }
11873                 field->type = mono_metadata_type_dup (klass->image, custom);
11874                 g_free (custom);
11875         } else {
11876                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, &error);
11877                 if (!is_ok (&error)) {
11878                         g_free (field);
11879                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11880                 }
11881         }
11882         if (fb->offset != -1)
11883                 field->offset = fb->offset;
11884         field->parent = klass;
11885         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11886
11887         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11888
11889         return field;
11890 }
11891 #endif
11892
11893 MonoType*
11894 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11895 {
11896         MonoError error;
11897         MonoClass *klass;
11898         MonoReflectionTypeBuilder *tb = NULL;
11899         gboolean is_dynamic = FALSE;
11900         MonoClass *geninst;
11901
11902         mono_loader_lock ();
11903
11904         if (is_sre_type_builder (mono_object_class (type))) {
11905                 tb = (MonoReflectionTypeBuilder *) type;
11906
11907                 is_dynamic = TRUE;
11908         } else if (is_sre_generic_instance (mono_object_class (type))) {
11909                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11910                 MonoReflectionType *gtd = rgi->generic_type;
11911
11912                 if (is_sre_type_builder (mono_object_class (gtd))) {
11913                         tb = (MonoReflectionTypeBuilder *)gtd;
11914                         is_dynamic = TRUE;
11915                 }
11916         }
11917
11918         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11919         if (tb && tb->generic_container)
11920                 mono_reflection_create_generic_class (tb);
11921
11922         MonoType *t = mono_reflection_type_get_handle (type, &error);
11923         mono_error_raise_exception (&error); /* FIXME don't raise here */
11924
11925         klass = mono_class_from_mono_type (t);
11926         if (!klass->generic_container) {
11927                 mono_loader_unlock ();
11928                 return NULL;
11929         }
11930
11931         if (klass->wastypebuilder) {
11932                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11933
11934                 is_dynamic = TRUE;
11935         }
11936
11937         mono_loader_unlock ();
11938
11939         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11940
11941         return &geninst->byval_arg;
11942 }
11943
11944 MonoClass*
11945 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11946 {
11947         MonoGenericClass *gclass;
11948         MonoGenericInst *inst;
11949
11950         g_assert (klass->generic_container);
11951
11952         inst = mono_metadata_get_generic_inst (type_argc, types);
11953         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11954
11955         return mono_generic_class_get_class (gclass);
11956 }
11957
11958 MonoReflectionMethod*
11959 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11960 {
11961         MonoError error;
11962         MonoClass *klass;
11963         MonoMethod *method, *inflated;
11964         MonoMethodInflated *imethod;
11965         MonoGenericContext tmp_context;
11966         MonoGenericInst *ginst;
11967         MonoType **type_argv;
11968         int count, i;
11969
11970         /*FIXME but this no longer should happen*/
11971         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11972 #ifndef DISABLE_REFLECTION_EMIT
11973                 MonoReflectionMethodBuilder *mb = NULL;
11974                 MonoType *tb;
11975                 MonoClass *klass;
11976
11977                 mb = (MonoReflectionMethodBuilder *) rmethod;
11978                 tb = mono_reflection_type_get_handle ((MonoReflectionType*)mb->type, &error);
11979                 mono_error_raise_exception (&error); /* FIXME don't raise here */
11980                 klass = mono_class_from_mono_type (tb);
11981
11982                 method = methodbuilder_to_mono_method (klass, mb, &error);
11983                 if (!method)
11984                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11985 #else
11986                 g_assert_not_reached ();
11987                 method = NULL;
11988 #endif
11989         } else {
11990                 method = rmethod->method;
11991         }
11992
11993         klass = method->klass;
11994
11995         if (method->is_inflated)
11996                 method = ((MonoMethodInflated *) method)->declaring;
11997
11998         count = mono_method_signature (method)->generic_param_count;
11999         if (count != mono_array_length (types))
12000                 return NULL;
12001
12002         type_argv = g_new0 (MonoType *, count);
12003         for (i = 0; i < count; i++) {
12004                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
12005                 type_argv [i] = mono_reflection_type_get_handle (garg, &error);
12006                 if (!is_ok (&error)) {
12007                         g_free (type_argv);
12008                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12009                 }
12010         }
12011         ginst = mono_metadata_get_generic_inst (count, type_argv);
12012         g_free (type_argv);
12013
12014         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
12015         tmp_context.method_inst = ginst;
12016
12017         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
12018         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12019         imethod = (MonoMethodInflated *) inflated;
12020
12021         /*FIXME but I think this is no longer necessary*/
12022         if (image_is_dynamic (method->klass->image)) {
12023                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12024                 /*
12025                  * This table maps metadata structures representing inflated methods/fields
12026                  * to the reflection objects representing their generic definitions.
12027                  */
12028                 mono_image_lock ((MonoImage*)image);
12029                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
12030                 mono_image_unlock ((MonoImage*)image);
12031         }
12032
12033         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
12034                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
12035         
12036         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
12037         mono_error_raise_exception (&error); /* FIXME don't raise here */
12038         return ret;
12039 }
12040
12041 #ifndef DISABLE_REFLECTION_EMIT
12042
12043 static MonoMethod *
12044 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
12045 {
12046         MonoMethodInflated *imethod;
12047         MonoGenericContext *context;
12048         int i;
12049
12050         /*
12051          * With generic code sharing the klass might not be inflated.
12052          * This can happen because classes inflated with their own
12053          * type arguments are "normalized" to the uninflated class.
12054          */
12055         if (!klass->generic_class)
12056                 return method;
12057
12058         context = mono_class_get_context (klass);
12059
12060         if (klass->method.count && klass->methods) {
12061                 /* Find the already created inflated method */
12062                 for (i = 0; i < klass->method.count; ++i) {
12063                         g_assert (klass->methods [i]->is_inflated);
12064                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
12065                                 break;
12066                 }
12067                 g_assert (i < klass->method.count);
12068                 imethod = (MonoMethodInflated*)klass->methods [i];
12069         } else {
12070                 MonoError error;
12071                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
12072                 mono_error_assert_ok (&error);
12073         }
12074
12075         if (method->is_generic && image_is_dynamic (method->klass->image)) {
12076                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
12077
12078                 mono_image_lock ((MonoImage*)image);
12079                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
12080                 mono_image_unlock ((MonoImage*)image);
12081         }
12082         return (MonoMethod *) imethod;
12083 }
12084
12085 static MonoMethod *
12086 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
12087 {
12088         MonoMethod *method;
12089         MonoClass *gklass;
12090
12091         mono_error_init (error);
12092
12093         MonoClass *type_class = mono_object_class (type);
12094
12095         if (is_sre_generic_instance (type_class)) {
12096                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
12097                 MonoType *generic_type = mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type, error);
12098                 return_val_if_nok (error, NULL);
12099                 gklass = mono_class_from_mono_type (generic_type);
12100         } else if (is_sre_type_builder (type_class)) {
12101                 MonoType *t = mono_reflection_type_get_handle (type, error);
12102                 return_val_if_nok (error, NULL);
12103                 gklass = mono_class_from_mono_type (t);
12104         } else if (type->type) {
12105                 gklass = mono_class_from_mono_type (type->type);
12106                 gklass = mono_class_get_generic_type_definition (gklass);
12107         } else {
12108                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
12109         }
12110
12111         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
12112                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
12113                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
12114                 else {
12115                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
12116                         if (!method)
12117                                 return NULL;
12118                 }
12119         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
12120                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
12121                 if (!method)
12122                         return NULL;
12123         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
12124                 method = ((MonoReflectionMethod *) obj)->method;
12125         else {
12126                 method = NULL; /* prevent compiler warning */
12127                 g_error ("can't handle type %s", obj->vtable->klass->name);
12128         }
12129
12130         MonoType *t = mono_reflection_type_get_handle (type, error);
12131         return_val_if_nok (error, NULL);
12132         return inflate_mono_method (mono_class_from_mono_type (t), method, obj);
12133 }
12134
12135 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
12136 void
12137 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
12138 {
12139         MonoError error;
12140         MonoGenericClass *gclass;
12141         MonoDynamicGenericClass *dgclass;
12142         MonoClass *klass, *gklass;
12143         MonoType *gtype;
12144         int i;
12145
12146         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type, &error);
12147         mono_error_raise_exception (&error); /* FIXME don't raise here */
12148         klass = mono_class_from_mono_type (gtype);
12149         g_assert (gtype->type == MONO_TYPE_GENERICINST);
12150         gclass = gtype->data.generic_class;
12151
12152         if (!gclass->is_dynamic)
12153                 return;
12154
12155         dgclass = (MonoDynamicGenericClass *) gclass;
12156
12157         if (dgclass->initialized)
12158                 return;
12159
12160         gklass = gclass->container_class;
12161         mono_class_init (gklass);
12162
12163         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
12164
12165         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
12166         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
12167         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
12168
12169         for (i = 0; i < dgclass->count_fields; i++) {
12170                 MonoError error;
12171                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
12172                 MonoClassField *field, *inflated_field = NULL;
12173
12174                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
12175                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
12176                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
12177                         field = ((MonoReflectionField *) obj)->field;
12178                 else {
12179                         field = NULL; /* prevent compiler warning */
12180                         g_assert_not_reached ();
12181                 }
12182
12183                 dgclass->fields [i] = *field;
12184                 dgclass->fields [i].parent = klass;
12185                 dgclass->fields [i].type = mono_class_inflate_generic_type_checked (
12186                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass), &error);
12187                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
12188                 dgclass->field_generic_types [i] = field->type;
12189                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
12190                 dgclass->field_objects [i] = obj;
12191
12192                 if (inflated_field) {
12193                         g_free (inflated_field);
12194                 } else {
12195                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
12196                 }
12197         }
12198
12199         dgclass->initialized = TRUE;
12200 }
12201
12202 void
12203 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12204 {
12205         MonoDynamicGenericClass *dgclass;
12206         int i;
12207
12208         g_assert (gclass->is_dynamic);
12209
12210         dgclass = (MonoDynamicGenericClass *)gclass;
12211
12212         for (i = 0; i < dgclass->count_fields; ++i) {
12213                 MonoClassField *field = dgclass->fields + i;
12214                 mono_metadata_free_type (field->type);
12215                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
12216         }
12217 }
12218
12219 static void
12220 fix_partial_generic_class (MonoClass *klass)
12221 {
12222         MonoClass *gklass = klass->generic_class->container_class;
12223         MonoDynamicGenericClass *dgclass;
12224         int i;
12225
12226         if (klass->wastypebuilder)
12227                 return;
12228
12229         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
12230         if (klass->parent != gklass->parent) {
12231                 MonoError error;
12232                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
12233                 if (mono_error_ok (&error)) {
12234                         MonoClass *parent = mono_class_from_mono_type (parent_type);
12235                         mono_metadata_free_type (parent_type);
12236                         if (parent != klass->parent) {
12237                                 /*fool mono_class_setup_parent*/
12238                                 klass->supertypes = NULL;
12239                                 mono_class_setup_parent (klass, parent);
12240                         }
12241                 } else {
12242                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12243                         mono_error_cleanup (&error);
12244                         if (gklass->wastypebuilder)
12245                                 klass->wastypebuilder = TRUE;
12246                         return;
12247                 }
12248         }
12249
12250         if (!dgclass->initialized)
12251                 return;
12252
12253         if (klass->method.count != gklass->method.count) {
12254                 klass->method.count = gklass->method.count;
12255                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
12256
12257                 for (i = 0; i < klass->method.count; i++) {
12258                         MonoError error;
12259                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
12260                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
12261                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12262                 }
12263         }
12264
12265         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
12266                 klass->interface_count = gklass->interface_count;
12267                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
12268                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12269
12270                 for (i = 0; i < gklass->interface_count; ++i) {
12271                         MonoError error;
12272                         MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), &error);
12273                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12274
12275                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
12276                         mono_metadata_free_type (iface_type);
12277
12278                         ensure_runtime_vtable (klass->interfaces [i], &error);
12279                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12280                 }
12281                 klass->interfaces_inited = 1;
12282         }
12283
12284         if (klass->field.count != gklass->field.count) {
12285                 klass->field.count = gklass->field.count;
12286                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
12287
12288                 for (i = 0; i < klass->field.count; i++) {
12289                         MonoError error;
12290                         klass->fields [i] = gklass->fields [i];
12291                         klass->fields [i].parent = klass;
12292                         klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), &error);
12293                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12294                 }
12295         }
12296
12297         /*We can only finish with this klass once it's parent has as well*/
12298         if (gklass->wastypebuilder)
12299                 klass->wastypebuilder = TRUE;
12300         return;
12301 }
12302
12303 /**
12304  * ensure_generic_class_runtime_vtable:
12305  * @klass a generic class
12306  * @error set on error
12307  *
12308  * Ensures that the generic container of @klass has a vtable and
12309  * returns TRUE on success.  On error returns FALSE and sets @error.
12310  */
12311 static gboolean
12312 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
12313 {
12314         MonoClass *gklass = klass->generic_class->container_class;
12315
12316         mono_error_init (error);
12317
12318         if (!ensure_runtime_vtable (gklass, error))
12319                 return FALSE;
12320
12321         fix_partial_generic_class (klass);
12322
12323         return TRUE;
12324 }
12325
12326 /**
12327  * ensure_runtime_vtable:
12328  * @klass the class
12329  * @error set on error
12330  *
12331  * Ensures that @klass has a vtable and returns TRUE on success. On
12332  * error returns FALSE and sets @error.
12333  */
12334 static gboolean
12335 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
12336 {
12337         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12338         int i, num, j;
12339
12340         mono_error_init (error);
12341
12342         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
12343                 return TRUE;
12344         if (klass->parent)
12345                 if (!ensure_runtime_vtable (klass->parent, error))
12346                         return FALSE;
12347
12348         if (tb) {
12349                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12350                 num += tb->num_methods;
12351                 klass->method.count = num;
12352                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
12353                 num = tb->ctors? mono_array_length (tb->ctors): 0;
12354                 for (i = 0; i < num; ++i) {
12355                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
12356                         if (!ctor)
12357                                 return FALSE;
12358                         klass->methods [i] = ctor;
12359                 }
12360                 num = tb->num_methods;
12361                 j = i;
12362                 for (i = 0; i < num; ++i) {
12363                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
12364                         if (!meth)
12365                                 return FALSE;
12366                         klass->methods [j++] = meth;
12367                 }
12368         
12369                 if (tb->interfaces) {
12370                         klass->interface_count = mono_array_length (tb->interfaces);
12371                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
12372                         for (i = 0; i < klass->interface_count; ++i) {
12373                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i, error);
12374                                 return_val_if_nok (error, FALSE);
12375                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
12376                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
12377                                         return FALSE;
12378                         }
12379                         klass->interfaces_inited = 1;
12380                 }
12381         } else if (klass->generic_class){
12382                 if (!ensure_generic_class_runtime_vtable (klass, error))
12383                         return FALSE;
12384         }
12385
12386         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
12387                 int slot_num = 0;
12388                 for (i = 0; i < klass->method.count; ++i) {
12389                         MonoMethod *im = klass->methods [i];
12390                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
12391                                 im->slot = slot_num++;
12392                 }
12393                 
12394                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
12395                 mono_class_setup_interface_offsets (klass);
12396                 mono_class_setup_interface_id (klass);
12397         }
12398
12399         /*
12400          * The generic vtable is needed even if image->run is not set since some
12401          * runtime code like ves_icall_Type_GetMethodsByName depends on 
12402          * method->slot being defined.
12403          */
12404
12405         /* 
12406          * tb->methods could not be freed since it is used for determining 
12407          * overrides during dynamic vtable construction.
12408          */
12409
12410         return TRUE;
12411 }
12412
12413 static MonoMethod*
12414 mono_reflection_method_get_handle (MonoObject *method)
12415 {
12416         MonoError error;
12417         MonoClass *klass = mono_object_class (method);
12418         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
12419                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12420                 return sr_method->method;
12421         }
12422         if (is_sre_method_builder (klass)) {
12423                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12424                 return mb->mhandle;
12425         }
12426         if (is_sre_method_on_tb_inst (klass)) {
12427                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12428                 MonoMethod *result;
12429                 /*FIXME move this to a proper method and unify with resolve_object*/
12430                 if (m->method_args) {
12431                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12432                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12433                 } else {
12434                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
12435                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12436                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12437                         MonoMethod *mono_method;
12438
12439                         if (is_sre_method_builder (mono_object_class (m->mb)))
12440                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12441                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12442                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12443                         else
12444                                 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)));
12445
12446                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12447                 }
12448                 return result;
12449         }
12450
12451         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12452         return NULL;
12453 }
12454
12455 void
12456 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12457 {
12458         MonoReflectionTypeBuilder *tb;
12459         int i, j, onum;
12460         MonoReflectionMethod *m;
12461
12462         *overrides = NULL;
12463         *num_overrides = 0;
12464
12465         g_assert (image_is_dynamic (klass->image));
12466
12467         if (!mono_class_get_ref_info (klass))
12468                 return;
12469
12470         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12471
12472         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12473
12474         onum = 0;
12475         if (tb->methods) {
12476                 for (i = 0; i < tb->num_methods; ++i) {
12477                         MonoReflectionMethodBuilder *mb = 
12478                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12479                         if (mb->override_methods)
12480                                 onum += mono_array_length (mb->override_methods);
12481                 }
12482         }
12483
12484         if (onum) {
12485                 *overrides = g_new0 (MonoMethod*, onum * 2);
12486
12487                 onum = 0;
12488                 for (i = 0; i < tb->num_methods; ++i) {
12489                         MonoReflectionMethodBuilder *mb = 
12490                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12491                         if (mb->override_methods) {
12492                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12493                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12494
12495                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12496                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12497
12498                                         g_assert (mb->mhandle);
12499
12500                                         onum ++;
12501                                 }
12502                         }
12503                 }
12504         }
12505
12506         *num_overrides = onum;
12507 }
12508
12509 static void
12510 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12511 {
12512         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12513         MonoReflectionFieldBuilder *fb;
12514         MonoClassField *field;
12515         MonoImage *image = klass->image;
12516         const char *p, *p2;
12517         int i;
12518         guint32 len, idx, real_size = 0;
12519
12520         klass->field.count = tb->num_fields;
12521         klass->field.first = 0;
12522
12523         mono_error_init (error);
12524
12525         if (tb->class_size) {
12526                 if ((tb->packing_size & 0xffffff00) != 0) {
12527                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12528                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12529                         return;
12530                 }
12531                 klass->packing_size = tb->packing_size;
12532                 real_size = klass->instance_size + tb->class_size;
12533         }
12534
12535         if (!klass->field.count) {
12536                 klass->instance_size = MAX (klass->instance_size, real_size);
12537                 return;
12538         }
12539         
12540         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12541         mono_class_alloc_ext (klass);
12542         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12543         /*
12544         This is, guess what, a hack.
12545         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12546         On the static path no field class is resolved, only types are built. This is the right thing to do
12547         but we suck.
12548         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12549         */
12550         klass->size_inited = 1;
12551
12552         for (i = 0; i < klass->field.count; ++i) {
12553                 MonoArray *rva_data;
12554                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12555                 field = &klass->fields [i];
12556                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12557                 if (!mono_error_ok (error))
12558                         return;
12559                 if (fb->attrs) {
12560                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12561                         return_if_nok (error);
12562                         field->type = mono_metadata_type_dup (klass->image, type);
12563                         field->type->attrs = fb->attrs;
12564                 } else {
12565                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
12566                         return_if_nok (error);
12567                 }
12568
12569                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12570                         char *base = mono_array_addr (rva_data, char, 0);
12571                         size_t size = mono_array_length (rva_data);
12572                         char *data = (char *)mono_image_alloc (klass->image, size);
12573                         memcpy (data, base, size);
12574                         klass->ext->field_def_values [i].data = data;
12575                 }
12576                 if (fb->offset != -1)
12577                         field->offset = fb->offset;
12578                 field->parent = klass;
12579                 fb->handle = field;
12580                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12581
12582                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12583                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12584                 }
12585                 if (fb->def_value) {
12586                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12587                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12588                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12589                         /* Copy the data from the blob since it might get realloc-ed */
12590                         p = assembly->blob.data + idx;
12591                         len = mono_metadata_decode_blob_size (p, &p2);
12592                         len += p2 - p;
12593                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12594                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12595                 }
12596         }
12597
12598         klass->instance_size = MAX (klass->instance_size, real_size);
12599         mono_class_layout_fields (klass);
12600 }
12601
12602 static void
12603 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12604 {
12605         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12606         MonoReflectionPropertyBuilder *pb;
12607         MonoImage *image = klass->image;
12608         MonoProperty *properties;
12609         int i;
12610
12611         mono_error_init (error);
12612
12613         if (!klass->ext)
12614                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12615
12616         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12617         klass->ext->property.first = 0;
12618
12619         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12620         klass->ext->properties = properties;
12621         for (i = 0; i < klass->ext->property.count; ++i) {
12622                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12623                 properties [i].parent = klass;
12624                 properties [i].attrs = pb->attrs;
12625                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12626                 if (!mono_error_ok (error))
12627                         return;
12628                 if (pb->get_method)
12629                         properties [i].get = pb->get_method->mhandle;
12630                 if (pb->set_method)
12631                         properties [i].set = pb->set_method->mhandle;
12632
12633                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12634                 if (pb->def_value) {
12635                         guint32 len, idx;
12636                         const char *p, *p2;
12637                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12638                         if (!klass->ext->prop_def_values)
12639                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12640                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12641                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12642                         /* Copy the data from the blob since it might get realloc-ed */
12643                         p = assembly->blob.data + idx;
12644                         len = mono_metadata_decode_blob_size (p, &p2);
12645                         len += p2 - p;
12646                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12647                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12648                 }
12649         }
12650 }
12651
12652 MonoReflectionEvent *
12653 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12654 {
12655         MonoError error;
12656         MonoEvent *event = g_new0 (MonoEvent, 1);
12657         MonoClass *klass;
12658
12659         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
12660         mono_error_raise_exception (&error); /* FIXME don't raise here */
12661         klass = mono_class_from_mono_type (type);
12662
12663         event->parent = klass;
12664         event->attrs = eb->attrs;
12665         event->name = mono_string_to_utf8 (eb->name);
12666         if (eb->add_method)
12667                 event->add = eb->add_method->mhandle;
12668         if (eb->remove_method)
12669                 event->remove = eb->remove_method->mhandle;
12670         if (eb->raise_method)
12671                 event->raise = eb->raise_method->mhandle;
12672
12673 #ifndef MONO_SMALL_CONFIG
12674         if (eb->other_methods) {
12675                 int j;
12676                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12677                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12678                         MonoReflectionMethodBuilder *mb = 
12679                                 mono_array_get (eb->other_methods,
12680                                                 MonoReflectionMethodBuilder*, j);
12681                         event->other [j] = mb->mhandle;
12682                 }
12683         }
12684 #endif
12685
12686         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12687         mono_error_raise_exception (&error); /* FIXME don't raise here */
12688         return ev_obj;
12689 }
12690
12691 static void
12692 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12693 {
12694         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12695         MonoReflectionEventBuilder *eb;
12696         MonoImage *image = klass->image;
12697         MonoEvent *events;
12698         int i;
12699
12700         mono_error_init (error);
12701
12702         if (!klass->ext)
12703                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12704
12705         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12706         klass->ext->event.first = 0;
12707
12708         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12709         klass->ext->events = events;
12710         for (i = 0; i < klass->ext->event.count; ++i) {
12711                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12712                 events [i].parent = klass;
12713                 events [i].attrs = eb->attrs;
12714                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12715                 if (!mono_error_ok (error))
12716                         return;
12717                 if (eb->add_method)
12718                         events [i].add = eb->add_method->mhandle;
12719                 if (eb->remove_method)
12720                         events [i].remove = eb->remove_method->mhandle;
12721                 if (eb->raise_method)
12722                         events [i].raise = eb->raise_method->mhandle;
12723
12724 #ifndef MONO_SMALL_CONFIG
12725                 if (eb->other_methods) {
12726                         int j;
12727                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12728                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12729                                 MonoReflectionMethodBuilder *mb = 
12730                                         mono_array_get (eb->other_methods,
12731                                                                         MonoReflectionMethodBuilder*, j);
12732                                 events [i].other [j] = mb->mhandle;
12733                         }
12734                 }
12735 #endif
12736                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12737         }
12738 }
12739
12740 static gboolean
12741 remove_instantiations_of_and_ensure_contents (gpointer key,
12742                                                   gpointer value,
12743                                                   gpointer user_data)
12744 {
12745         MonoType *type = (MonoType*)key;
12746         MonoClass *klass = (MonoClass*)user_data;
12747
12748         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12749                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12750                 return TRUE;
12751         } else
12752                 return FALSE;
12753 }
12754
12755 static void
12756 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12757 {
12758         mono_error_init (error);
12759         int i;
12760
12761         if (!arr)
12762                 return;
12763
12764         for (i = 0; i < mono_array_length (arr); ++i) {
12765                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12766                 if (!mono_error_ok (error))
12767                         break;
12768         }
12769 }
12770
12771 MonoReflectionType*
12772 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12773 {
12774         MonoError error;
12775         MonoClass *klass;
12776         MonoDomain* domain;
12777         MonoReflectionType* res;
12778         int i, j;
12779
12780         domain = mono_object_domain (tb);
12781         klass = mono_class_from_mono_type (tb->type.type);
12782
12783         /*
12784          * Check for user defined Type subclasses.
12785          */
12786         RESOLVE_TYPE (tb->parent, &error);
12787         mono_error_raise_exception (&error); /* FIXME don't raise here */
12788         check_array_for_usertypes (tb->interfaces, &error);
12789         mono_error_raise_exception (&error); /*FIXME don't raise here */
12790         if (tb->fields) {
12791                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12792                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12793                         if (fb) {
12794                                 RESOLVE_TYPE (fb->type, &error);
12795                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12796                                 check_array_for_usertypes (fb->modreq, &error);
12797                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12798                                 check_array_for_usertypes (fb->modopt, &error);
12799                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12800                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12801                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12802                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12803                                 }
12804                         }
12805                 }
12806         }
12807         if (tb->methods) {
12808                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12809                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12810                         if (mb) {
12811                                 RESOLVE_TYPE (mb->rtype, &error);
12812                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12813                                 check_array_for_usertypes (mb->return_modreq, &error);
12814                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12815                                 check_array_for_usertypes (mb->return_modopt, &error);
12816                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
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         if (tb->ctors) {
12833                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12834                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12835                         if (mb) {
12836                                 check_array_for_usertypes (mb->parameters, &error);
12837                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12838                                 if (mb->param_modreq)
12839                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12840                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12841                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12842                                         }
12843                                 if (mb->param_modopt)
12844                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12845                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12846                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12847                                         }
12848                         }
12849                 }
12850         }
12851
12852         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12853
12854         /* 
12855          * we need to lock the domain because the lock will be taken inside
12856          * So, we need to keep the locking order correct.
12857          */
12858         mono_loader_lock ();
12859         mono_domain_lock (domain);
12860         if (klass->wastypebuilder) {
12861                 mono_domain_unlock (domain);
12862                 mono_loader_unlock ();
12863
12864                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12865                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12866
12867                 return res;
12868         }
12869         /*
12870          * Fields to set in klass:
12871          * the various flags: delegate/unicode/contextbound etc.
12872          */
12873         klass->flags = tb->attrs;
12874         klass->has_cctor = 1;
12875         klass->has_finalize = 1;
12876         klass->has_finalize_inited = 1;
12877
12878         mono_class_setup_parent (klass, klass->parent);
12879         /* fool mono_class_setup_supertypes */
12880         klass->supertypes = NULL;
12881         mono_class_setup_supertypes (klass);
12882         mono_class_setup_mono_type (klass);
12883
12884 #if 0
12885         if (!((MonoDynamicImage*)klass->image)->run) {
12886                 if (klass->generic_container) {
12887                         /* FIXME: The code below can't handle generic classes */
12888                         klass->wastypebuilder = TRUE;
12889                         mono_loader_unlock ();
12890                         mono_domain_unlock (domain);
12891
12892                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12893                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12894
12895                         return res;
12896                 }
12897         }
12898 #endif
12899
12900         /* enums are done right away */
12901         if (!klass->enumtype)
12902                 if (!ensure_runtime_vtable (klass, &error))
12903                         goto failure;
12904
12905         if (tb->subtypes) {
12906                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12907                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12908                         mono_class_alloc_ext (klass);
12909                         MonoType *subtype = mono_reflection_type_get_handle ((MonoReflectionType*)subtb, &error);
12910                         if (!is_ok (&error)) goto failure;
12911                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (subtype));
12912                 }
12913         }
12914
12915         klass->nested_classes_inited = TRUE;
12916
12917         /* fields and object layout */
12918         if (klass->parent) {
12919                 if (!klass->parent->size_inited)
12920                         mono_class_init (klass->parent);
12921                 klass->instance_size = klass->parent->instance_size;
12922                 klass->sizes.class_size = 0;
12923                 klass->min_align = klass->parent->min_align;
12924                 /* if the type has no fields we won't call the field_setup
12925                  * routine which sets up klass->has_references.
12926                  */
12927                 klass->has_references |= klass->parent->has_references;
12928         } else {
12929                 klass->instance_size = sizeof (MonoObject);
12930                 klass->min_align = 1;
12931         }
12932
12933         /* FIXME: handle packing_size and instance_size */
12934         typebuilder_setup_fields (klass, &error);
12935         if (!mono_error_ok (&error))
12936                 goto failure;
12937         typebuilder_setup_properties (klass, &error);
12938         if (!mono_error_ok (&error))
12939                 goto failure;
12940
12941         typebuilder_setup_events (klass, &error);
12942         if (!mono_error_ok (&error))
12943                 goto failure;
12944
12945         klass->wastypebuilder = TRUE;
12946
12947         /* 
12948          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12949          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12950          * we want to return normal System.MonoType objects, so clear these out from the cache.
12951          *
12952          * Together with this we must ensure the contents of all instances to match the created type.
12953          */
12954         if (domain->type_hash && klass->generic_container)
12955                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12956
12957         mono_domain_unlock (domain);
12958         mono_loader_unlock ();
12959
12960         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12961                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12962                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12963         }
12964
12965         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12966         mono_error_raise_exception (&error); /* FIXME don't raise here */
12967
12968         g_assert (res != (MonoReflectionType*)tb);
12969
12970         return res;
12971
12972 failure:
12973         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12974         klass->wastypebuilder = TRUE;
12975         mono_domain_unlock (domain);
12976         mono_loader_unlock ();
12977         mono_error_raise_exception (&error);
12978         return NULL;
12979 }
12980
12981 void
12982 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12983 {
12984         MonoGenericParamFull *param;
12985         MonoImage *image;
12986         MonoClass *pklass;
12987         MonoError error;
12988
12989         image = &gparam->tbuilder->module->dynamic_image->image;
12990
12991         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12992
12993         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12994         g_assert (mono_error_ok (&error));
12995         param->param.num = gparam->index;
12996
12997         if (gparam->mbuilder) {
12998                 if (!gparam->mbuilder->generic_container) {
12999                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->mbuilder->type, &error);
13000                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13001
13002                         MonoClass *klass = mono_class_from_mono_type (tb);
13003                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13004                         gparam->mbuilder->generic_container->is_method = TRUE;
13005                         /* 
13006                          * Cannot set owner.method, since the MonoMethod is not created yet.
13007                          * Set the image field instead, so type_in_image () works.
13008                          */
13009                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
13010                         gparam->mbuilder->generic_container->owner.image = klass->image;
13011                 }
13012                 param->param.owner = gparam->mbuilder->generic_container;
13013         } else if (gparam->tbuilder) {
13014                 if (!gparam->tbuilder->generic_container) {
13015                         MonoType *tb = mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder, &error);
13016                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13017                         MonoClass *klass = mono_class_from_mono_type (tb);
13018                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
13019                         gparam->tbuilder->generic_container->owner.klass = klass;
13020                 }
13021                 param->param.owner = gparam->tbuilder->generic_container;
13022         }
13023
13024         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
13025
13026         gparam->type.type = &pklass->byval_arg;
13027
13028         mono_class_set_ref_info (pklass, gparam);
13029         mono_image_append_class_to_reflection_info_set (pklass);
13030 }
13031
13032 MonoArray *
13033 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13034 {
13035         MonoError error;
13036         MonoReflectionModuleBuilder *module = sig->module;
13037         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
13038         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13039         guint32 buflen, i;
13040         MonoArray *result;
13041         SigBuffer buf;
13042
13043         check_array_for_usertypes (sig->arguments, &error);
13044         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13045
13046         sigbuffer_init (&buf, 32);
13047
13048         sigbuffer_add_value (&buf, 0x07);
13049         sigbuffer_add_value (&buf, na);
13050         if (assembly != NULL){
13051                 for (i = 0; i < na; ++i) {
13052                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13053                         encode_reflection_type (assembly, type, &buf, &error);
13054                         if (!is_ok (&error)) goto fail;
13055                 }
13056         }
13057
13058         buflen = buf.p - buf.buf;
13059         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13060         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13061         sigbuffer_free (&buf);
13062         return result;
13063 fail:
13064         sigbuffer_free (&buf);
13065         mono_error_raise_exception (&error); /* FIXME don't raise here */
13066         return NULL;
13067 }
13068
13069 MonoArray *
13070 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13071 {
13072         MonoError error;
13073         MonoDynamicImage *assembly = sig->module->dynamic_image;
13074         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
13075         guint32 buflen, i;
13076         MonoArray *result;
13077         SigBuffer buf;
13078
13079         check_array_for_usertypes (sig->arguments, &error);
13080         mono_error_raise_exception (&error); /* FIXME: don't raise here */
13081
13082         sigbuffer_init (&buf, 32);
13083
13084         sigbuffer_add_value (&buf, 0x06);
13085         for (i = 0; i < na; ++i) {
13086                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
13087                 encode_reflection_type (assembly, type, &buf, &error);
13088                 if (!is_ok (&error))
13089                         goto fail;
13090         }
13091
13092         buflen = buf.p - buf.buf;
13093         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
13094         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
13095         sigbuffer_free (&buf);
13096
13097         return result;
13098 fail:
13099         sigbuffer_free (&buf);
13100         mono_error_raise_exception (&error); /* FIXME don't raise here */
13101         return NULL;
13102 }
13103
13104 typedef struct {
13105         MonoMethod *handle;
13106         MonoDomain *domain;
13107 } DynamicMethodReleaseData;
13108
13109 /*
13110  * The runtime automatically clean up those after finalization.
13111 */      
13112 static MonoReferenceQueue *dynamic_method_queue;
13113
13114 static void
13115 free_dynamic_method (void *dynamic_method)
13116 {
13117         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
13118         MonoDomain *domain = data->domain;
13119         MonoMethod *method = data->handle;
13120         guint32 dis_link;
13121
13122         mono_domain_lock (domain);
13123         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
13124         g_hash_table_remove (domain->method_to_dyn_method, method);
13125         mono_domain_unlock (domain);
13126         g_assert (dis_link);
13127         mono_gchandle_free (dis_link);
13128
13129         mono_runtime_free_method (domain, method);
13130         g_free (data);
13131 }
13132
13133 void 
13134 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13135 {
13136         MonoError error;
13137         MonoReferenceQueue *queue;
13138         MonoMethod *handle;
13139         DynamicMethodReleaseData *release_data;
13140         ReflectionMethodBuilder rmb;
13141         MonoMethodSignature *sig;
13142         MonoClass *klass;
13143         MonoDomain *domain;
13144         GSList *l;
13145         int i;
13146
13147         if (mono_runtime_is_shutting_down ())
13148                 mono_raise_exception (mono_get_exception_invalid_operation (""));
13149
13150         if (!(queue = dynamic_method_queue)) {
13151                 mono_loader_lock ();
13152                 if (!(queue = dynamic_method_queue))
13153                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
13154                 mono_loader_unlock ();
13155         }
13156
13157         sig = dynamic_method_to_signature (mb);
13158
13159         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
13160
13161         /*
13162          * Resolve references.
13163          */
13164         /* 
13165          * Every second entry in the refs array is reserved for storing handle_class,
13166          * which is needed by the ldtoken implementation in the JIT.
13167          */
13168         rmb.nrefs = mb->nrefs;
13169         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
13170         for (i = 0; i < mb->nrefs; i += 2) {
13171                 MonoClass *handle_class;
13172                 gpointer ref;
13173                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
13174
13175                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13176                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13177                         /*
13178                          * The referenced DynamicMethod should already be created by the managed
13179                          * code, except in the case of circular references. In that case, we store
13180                          * method in the refs array, and fix it up later when the referenced 
13181                          * DynamicMethod is created.
13182                          */
13183                         if (method->mhandle) {
13184                                 ref = method->mhandle;
13185                         } else {
13186                                 /* FIXME: GC object stored in unmanaged memory */
13187                                 ref = method;
13188
13189                                 /* FIXME: GC object stored in unmanaged memory */
13190                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
13191                         }
13192                         handle_class = mono_defaults.methodhandle_class;
13193                 } else {
13194                         MonoException *ex = NULL;
13195                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
13196                         if (!ref)
13197                                 ex = mono_get_exception_type_load (NULL, NULL);
13198                         else if (mono_security_core_clr_enabled ())
13199                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
13200
13201                         if (ex) {
13202                                 g_free (rmb.refs);
13203                                 mono_raise_exception (ex);
13204                                 return;
13205                         }
13206                 }
13207
13208                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
13209                 rmb.refs [i + 1] = handle_class;
13210         }               
13211
13212         if (mb->owner) {
13213                 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, &error);
13214                 if (!is_ok (&error)) {
13215                         g_free (rmb.refs);
13216                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13217                 }
13218                 klass = mono_class_from_mono_type (owner_type);
13219         } else {
13220                 klass = mono_defaults.object_class;
13221         }
13222
13223         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
13224         release_data = g_new (DynamicMethodReleaseData, 1);
13225         release_data->handle = handle;
13226         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
13227         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
13228                 g_free (release_data);
13229
13230         /* Fix up refs entries pointing at us */
13231         for (l = mb->referenced_by; l; l = l->next) {
13232                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
13233                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
13234                 gpointer *data;
13235                 
13236                 g_assert (method->mhandle);
13237
13238                 data = (gpointer*)wrapper->method_data;
13239                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
13240                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
13241                                 data [i + 1] = mb->mhandle;
13242                 }
13243         }
13244         g_slist_free (mb->referenced_by);
13245
13246         g_free (rmb.refs);
13247
13248         /* ilgen is no longer needed */
13249         mb->ilgen = NULL;
13250
13251         domain = mono_domain_get ();
13252         mono_domain_lock (domain);
13253         if (!domain->method_to_dyn_method)
13254                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
13255         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
13256         mono_domain_unlock (domain);
13257 }
13258
13259 #endif /* DISABLE_REFLECTION_EMIT */
13260
13261 /**
13262  * 
13263  * mono_reflection_is_valid_dynamic_token:
13264  * 
13265  * Returns TRUE if token is valid.
13266  * 
13267  */
13268 gboolean
13269 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
13270 {
13271         return lookup_dyn_token (image, token) != NULL;
13272 }
13273
13274 MonoMethodSignature *
13275 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
13276 {
13277         MonoMethodSignature *sig;
13278         g_assert (image_is_dynamic (image));
13279
13280         mono_error_init (error);
13281
13282         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
13283         if (sig)
13284                 return sig;
13285
13286         return mono_method_signature_checked (method, error);
13287 }
13288
13289 #ifndef DISABLE_REFLECTION_EMIT
13290
13291 /**
13292  * mono_reflection_lookup_dynamic_token:
13293  *
13294  * Finish the Builder object pointed to by TOKEN and return the corresponding
13295  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
13296  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
13297  * mapping table.
13298  *
13299  * LOCKING: Take the loader lock
13300  */
13301 gpointer
13302 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13303 {
13304         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
13305         MonoObject *obj;
13306         MonoClass *klass;
13307
13308         obj = lookup_dyn_token (assembly, token);
13309         if (!obj) {
13310                 if (valid_token)
13311                         g_error ("Could not find required dynamic token 0x%08x", token);
13312                 else
13313                         return NULL;
13314         }
13315
13316         if (!handle_class)
13317                 handle_class = &klass;
13318         return resolve_object (image, obj, handle_class, context);
13319 }
13320
13321 /*
13322  * ensure_complete_type:
13323  *
13324  *   Ensure that KLASS is completed if it is a dynamic type, or references
13325  * dynamic types.
13326  */
13327 static void
13328 ensure_complete_type (MonoClass *klass)
13329 {
13330         MonoError error;
13331
13332         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
13333                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
13334
13335                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13336                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13337
13338                 // Asserting here could break a lot of code
13339                 //g_assert (klass->wastypebuilder);
13340         }
13341
13342         if (klass->generic_class) {
13343                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
13344                 int i;
13345
13346                 for (i = 0; i < inst->type_argc; ++i) {
13347                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
13348                 }
13349         }
13350 }
13351
13352 static gpointer
13353 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
13354 {
13355         MonoError error;
13356         gpointer result = NULL;
13357
13358         if (strcmp (obj->vtable->klass->name, "String") == 0) {
13359                 result = mono_string_intern_checked ((MonoString*)obj, &error);
13360                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13361                 *handle_class = mono_defaults.string_class;
13362                 g_assert (result);
13363         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
13364                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13365                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13366                 MonoClass *mc = mono_class_from_mono_type (type);
13367                 if (!mono_class_init (mc))
13368                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
13369
13370                 if (context) {
13371                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13372                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13373
13374                         result = mono_class_from_mono_type (inflated);
13375                         mono_metadata_free_type (inflated);
13376                 } else {
13377                         result = mono_class_from_mono_type (type);
13378                 }
13379                 *handle_class = mono_defaults.typehandle_class;
13380                 g_assert (result);
13381         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
13382                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
13383                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
13384                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
13385                 result = ((MonoReflectionMethod*)obj)->method;
13386                 if (context) {
13387                         MonoError error;
13388                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13389                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13390                 }
13391                 *handle_class = mono_defaults.methodhandle_class;
13392                 g_assert (result);
13393         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
13394                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
13395                 result = mb->mhandle;
13396                 if (!result) {
13397                         /* Type is not yet created */
13398                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
13399
13400                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13401                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13402
13403                         /*
13404                          * Hopefully this has been filled in by calling CreateType() on the
13405                          * TypeBuilder.
13406                          */
13407                         /*
13408                          * TODO: This won't work if the application finishes another 
13409                          * TypeBuilder instance instead of this one.
13410                          */
13411                         result = mb->mhandle;
13412                 }
13413                 if (context) {
13414                         MonoError error;
13415                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13416                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13417                 }
13418                 *handle_class = mono_defaults.methodhandle_class;
13419         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
13420                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
13421
13422                 result = cb->mhandle;
13423                 if (!result) {
13424                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
13425
13426                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13427                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13428                         result = cb->mhandle;
13429                 }
13430                 if (context) {
13431                         MonoError error;
13432                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13433                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
13434                 }
13435                 *handle_class = mono_defaults.methodhandle_class;
13436         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
13437                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
13438
13439                 ensure_complete_type (field->parent);
13440                 if (context) {
13441                         MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, &error);
13442                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13443
13444                         MonoClass *klass = mono_class_from_mono_type (inflated);
13445                         MonoClassField *inflated_field;
13446                         gpointer iter = NULL;
13447                         mono_metadata_free_type (inflated);
13448                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
13449                                 if (!strcmp (field->name, inflated_field->name))
13450                                         break;
13451                         }
13452                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
13453                         result = inflated_field;
13454                 } else {
13455                         result = field;
13456                 }
13457                 *handle_class = mono_defaults.fieldhandle_class;
13458                 g_assert (result);
13459         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13460                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13461                 result = fb->handle;
13462
13463                 if (!result) {
13464                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13465
13466                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13467                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13468                         result = fb->handle;
13469                 }
13470
13471                 if (fb->handle && fb->handle->parent->generic_container) {
13472                         MonoClass *klass = fb->handle->parent;
13473                         MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, context, &error);
13474                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13475
13476                         MonoClass *inflated = mono_class_from_mono_type (type);
13477
13478                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13479                         g_assert (result);
13480                         mono_metadata_free_type (type);
13481                 }
13482                 *handle_class = mono_defaults.fieldhandle_class;
13483         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13484                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13485                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, &error);
13486                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13487                 MonoClass *klass;
13488
13489                 klass = type->data.klass;
13490                 if (klass->wastypebuilder) {
13491                         /* Already created */
13492                         result = klass;
13493                 }
13494                 else {
13495                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13496                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13497                         result = type->data.klass;
13498                         g_assert (result);
13499                 }
13500                 *handle_class = mono_defaults.typehandle_class;
13501         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13502                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13503                 MonoMethodSignature *sig;
13504                 int nargs, i;
13505
13506                 if (helper->arguments)
13507                         nargs = mono_array_length (helper->arguments);
13508                 else
13509                         nargs = 0;
13510
13511                 sig = mono_metadata_signature_alloc (image, nargs);
13512                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13513                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13514
13515                 if (helper->unmanaged_call_conv) { /* unmanaged */
13516                         sig->call_convention = helper->unmanaged_call_conv - 1;
13517                         sig->pinvoke = TRUE;
13518                 } else if (helper->call_conv & 0x02) {
13519                         sig->call_convention = MONO_CALL_VARARG;
13520                 } else {
13521                         sig->call_convention = MONO_CALL_DEFAULT;
13522                 }
13523
13524                 sig->param_count = nargs;
13525                 /* TODO: Copy type ? */
13526                 sig->ret = helper->return_type->type;
13527                 for (i = 0; i < nargs; ++i) {
13528                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i, &error);
13529                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13530                 }
13531
13532                 result = sig;
13533                 *handle_class = NULL;
13534         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13535                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13536                 /* Already created by the managed code */
13537                 g_assert (method->mhandle);
13538                 result = method->mhandle;
13539                 *handle_class = mono_defaults.methodhandle_class;
13540         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13541                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13542                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13543                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13544                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13545
13546                 result = mono_class_from_mono_type (type);
13547                 *handle_class = mono_defaults.typehandle_class;
13548                 g_assert (result);
13549                 mono_metadata_free_type (type);
13550         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13551                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, &error);
13552                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13553                 type = mono_class_inflate_generic_type_checked (type, context, &error);
13554                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13555
13556                 result = mono_class_from_mono_type (type);
13557                 *handle_class = mono_defaults.typehandle_class;
13558                 g_assert (result);
13559                 mono_metadata_free_type (type);
13560         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13561                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13562                 MonoClass *inflated;
13563                 MonoType *type;
13564                 MonoClassField *field;
13565
13566                 if (is_sre_field_builder (mono_object_class (f->fb)))
13567                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13568                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13569                         field = ((MonoReflectionField*)f->fb)->field;
13570                 else
13571                         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)));
13572
13573                 MonoType *finst = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst, &error);
13574                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13575                 type = mono_class_inflate_generic_type_checked (finst, context, &error);
13576                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13577
13578                 inflated = mono_class_from_mono_type (type);
13579
13580                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13581                 ensure_complete_type (field->parent);
13582                 g_assert (result);
13583                 mono_metadata_free_type (type);
13584                 *handle_class = mono_defaults.fieldhandle_class;
13585         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13586                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13587                 MonoType *cinst = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst, &error);
13588                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13589                 MonoType *type = mono_class_inflate_generic_type_checked (cinst, context, &error);
13590                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13591
13592                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13593                 MonoMethod *method;
13594
13595                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13596                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13597                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13598                         method = ((MonoReflectionMethod *)c->cb)->method;
13599                 else
13600                         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)));
13601
13602                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13603                 *handle_class = mono_defaults.methodhandle_class;
13604                 mono_metadata_free_type (type);
13605         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13606                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13607                 if (m->method_args) {
13608                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13609                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13610                         if (context) {
13611                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13612                                 mono_error_assert_ok (&error);
13613                         }
13614                 } else {
13615                         MonoType *minst = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst, &error);
13616                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13617                         MonoType *type = mono_class_inflate_generic_type_checked (minst, context, &error);
13618                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13619
13620                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13621                         MonoMethod *method;
13622
13623                         if (is_sre_method_builder (mono_object_class (m->mb)))
13624                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13625                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13626                                 method = ((MonoReflectionMethod *)m->mb)->method;
13627                         else
13628                                 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)));
13629
13630                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13631                         mono_metadata_free_type (type);
13632                 }
13633                 *handle_class = mono_defaults.methodhandle_class;
13634         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13635                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13636                 MonoType *mtype;
13637                 MonoClass *klass;
13638                 MonoMethod *method;
13639                 gpointer iter;
13640                 char *name;
13641
13642                 mtype = mono_reflection_type_get_handle (m->parent, &error);
13643                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13644                 klass = mono_class_from_mono_type (mtype);
13645
13646                 /* Find the method */
13647
13648                 name = mono_string_to_utf8 (m->name);
13649                 iter = NULL;
13650                 while ((method = mono_class_get_methods (klass, &iter))) {
13651                         if (!strcmp (method->name, name))
13652                                 break;
13653                 }
13654                 g_free (name);
13655
13656                 // FIXME:
13657                 g_assert (method);
13658                 // FIXME: Check parameters/return value etc. match
13659
13660                 result = method;
13661                 *handle_class = mono_defaults.methodhandle_class;
13662         } else if (is_sre_array (mono_object_get_class(obj)) ||
13663                                 is_sre_byref (mono_object_get_class(obj)) ||
13664                                 is_sre_pointer (mono_object_get_class(obj))) {
13665                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13666                 MonoType *type = mono_reflection_type_get_handle (ref_type, &error);
13667                 mono_error_raise_exception (&error); /* FIXME don't raise here */
13668
13669                 if (context) {
13670                         MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, &error);
13671                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13672
13673                         result = mono_class_from_mono_type (inflated);
13674                         mono_metadata_free_type (inflated);
13675                 } else {
13676                         result = mono_class_from_mono_type (type);
13677                 }
13678                 *handle_class = mono_defaults.typehandle_class;
13679         } else {
13680                 g_print ("%s\n", obj->vtable->klass->name);
13681                 g_assert_not_reached ();
13682         }
13683         return result;
13684 }
13685
13686 #else /* DISABLE_REFLECTION_EMIT */
13687
13688 MonoArray*
13689 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13690 {
13691         g_assert_not_reached ();
13692         return NULL;
13693 }
13694
13695 void
13696 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13697 {
13698         g_assert_not_reached ();
13699 }
13700
13701 void
13702 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13703 {
13704         g_assert_not_reached ();
13705 }
13706
13707 void
13708 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13709 {
13710         g_assert_not_reached ();
13711 }
13712
13713 void
13714 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13715 {
13716         g_assert_not_reached ();
13717 }
13718
13719 void
13720 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13721 {
13722         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13723 }
13724
13725 void
13726 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13727 {
13728         g_assert_not_reached ();
13729 }
13730
13731 void
13732 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13733 {
13734         g_assert_not_reached ();
13735 }
13736
13737 MonoReflectionModule *
13738 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13739 {
13740         g_assert_not_reached ();
13741         return NULL;
13742 }
13743
13744 guint32
13745 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13746 {
13747         g_assert_not_reached ();
13748         return 0;
13749 }
13750
13751 guint32
13752 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13753 {
13754         g_assert_not_reached ();
13755         return 0;
13756 }
13757
13758 guint32
13759 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13760                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13761 {
13762         g_assert_not_reached ();
13763         return 0;
13764 }
13765
13766 void
13767 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13768 {
13769 }
13770
13771 void
13772 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13773 {
13774         g_assert_not_reached ();
13775 }
13776
13777 void
13778 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13779 {
13780         *overrides = NULL;
13781         *num_overrides = 0;
13782 }
13783
13784 MonoReflectionEvent *
13785 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13786 {
13787         g_assert_not_reached ();
13788         return NULL;
13789 }
13790
13791 MonoReflectionType*
13792 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13793 {
13794         g_assert_not_reached ();
13795         return NULL;
13796 }
13797
13798 void
13799 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13800 {
13801         g_assert_not_reached ();
13802 }
13803
13804 MonoArray *
13805 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13806 {
13807         g_assert_not_reached ();
13808         return NULL;
13809 }
13810
13811 MonoArray *
13812 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13813 {
13814         g_assert_not_reached ();
13815         return NULL;
13816 }
13817
13818 void 
13819 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13820 {
13821 }
13822
13823 gpointer
13824 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13825 {
13826         return NULL;
13827 }
13828
13829 MonoType*
13830 mono_reflection_type_get_handle (MonoReflectionType* ref)
13831 {
13832         if (!ref)
13833                 return NULL;
13834         return ref->type;
13835 }
13836
13837 void
13838 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13839 {
13840         g_assert_not_reached ();
13841 }
13842
13843 #endif /* DISABLE_REFLECTION_EMIT */
13844
13845 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13846 const static guint32 declsec_flags_map[] = {
13847         0x00000000,                                     /* empty */
13848         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13849         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13850         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13851         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13852         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13853         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13854         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13855         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13856         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13857         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13858         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13859         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13860         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13861         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13862         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13863         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13864         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13865         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13866 };
13867
13868 /*
13869  * Returns flags that includes all available security action associated to the handle.
13870  * @token: metadata token (either for a class or a method)
13871  * @image: image where resides the metadata.
13872  */
13873 static guint32
13874 mono_declsec_get_flags (MonoImage *image, guint32 token)
13875 {
13876         int index = mono_metadata_declsec_from_index (image, token);
13877         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13878         guint32 result = 0;
13879         guint32 action;
13880         int i;
13881
13882         /* HasSecurity can be present for other, not specially encoded, attributes,
13883            e.g. SuppressUnmanagedCodeSecurityAttribute */
13884         if (index < 0)
13885                 return 0;
13886
13887         for (i = index; i < t->rows; i++) {
13888                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13889
13890                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13891                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13892                         break;
13893
13894                 action = cols [MONO_DECL_SECURITY_ACTION];
13895                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13896                         result |= declsec_flags_map [action];
13897                 } else {
13898                         g_assert_not_reached ();
13899                 }
13900         }
13901         return result;
13902 }
13903
13904 /*
13905  * Get the security actions (in the form of flags) associated with the specified method.
13906  *
13907  * @method: The method for which we want the declarative security flags.
13908  * Return the declarative security flags for the method (only).
13909  *
13910  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13911  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13912  */
13913 guint32
13914 mono_declsec_flags_from_method (MonoMethod *method)
13915 {
13916         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13917                 /* FIXME: No cache (for the moment) */
13918                 guint32 idx = mono_method_get_index (method);
13919                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13920                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13921                 return mono_declsec_get_flags (method->klass->image, idx);
13922         }
13923         return 0;
13924 }
13925
13926 /*
13927  * Get the security actions (in the form of flags) associated with the specified class.
13928  *
13929  * @klass: The class for which we want the declarative security flags.
13930  * Return the declarative security flags for the class.
13931  *
13932  * Note: We cache the flags inside the MonoClass structure as this will get 
13933  *       called very often (at least for each method).
13934  */
13935 guint32
13936 mono_declsec_flags_from_class (MonoClass *klass)
13937 {
13938         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13939                 if (!klass->ext || !klass->ext->declsec_flags) {
13940                         guint32 idx;
13941
13942                         idx = mono_metadata_token_index (klass->type_token);
13943                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13944                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13945                         mono_loader_lock ();
13946                         mono_class_alloc_ext (klass);
13947                         mono_loader_unlock ();
13948                         /* we cache the flags on classes */
13949                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13950                 }
13951                 return klass->ext->declsec_flags;
13952         }
13953         return 0;
13954 }
13955
13956 /*
13957  * Get the security actions (in the form of flags) associated with the specified assembly.
13958  *
13959  * @assembly: The assembly for which we want the declarative security flags.
13960  * Return the declarative security flags for the assembly.
13961  */
13962 guint32
13963 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13964 {
13965         guint32 idx = 1; /* there is only one assembly */
13966         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13967         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13968         return mono_declsec_get_flags (assembly->image, idx);
13969 }
13970
13971
13972 /*
13973  * Fill actions for the specific index (which may either be an encoded class token or
13974  * an encoded method token) from the metadata image.
13975  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13976  */
13977 static MonoBoolean
13978 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13979         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13980 {
13981         MonoBoolean result = FALSE;
13982         MonoTableInfo *t;
13983         guint32 cols [MONO_DECL_SECURITY_SIZE];
13984         int index = mono_metadata_declsec_from_index (image, token);
13985         int i;
13986
13987         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13988         for (i = index; i < t->rows; i++) {
13989                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13990
13991                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13992                         return result;
13993
13994                 /* if present only replace (class) permissions with method permissions */
13995                 /* if empty accept either class or method permissions */
13996                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13997                         if (!actions->demand.blob) {
13998                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13999                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14000                                 actions->demand.blob = (char*) (blob + 2);
14001                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
14002                                 result = TRUE;
14003                         }
14004                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
14005                         if (!actions->noncasdemand.blob) {
14006                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14007                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14008                                 actions->noncasdemand.blob = (char*) (blob + 2);
14009                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
14010                                 result = TRUE;
14011                         }
14012                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
14013                         if (!actions->demandchoice.blob) {
14014                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14015                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
14016                                 actions->demandchoice.blob = (char*) (blob + 2);
14017                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
14018                                 result = TRUE;
14019                         }
14020                 }
14021         }
14022
14023         return result;
14024 }
14025
14026 static MonoBoolean
14027 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
14028         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14029 {
14030         guint32 idx = mono_metadata_token_index (klass->type_token);
14031         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14032         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14033         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
14034 }
14035
14036 static MonoBoolean
14037 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
14038         guint32 id_std, guint32 id_noncas, guint32 id_choice)
14039 {
14040         guint32 idx = mono_method_get_index (method);
14041         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14042         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14043         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
14044 }
14045
14046 /*
14047  * Collect all actions (that requires to generate code in mini) assigned for
14048  * the specified method.
14049  * Note: Don't use the content of actions if the function return FALSE.
14050  */
14051 MonoBoolean
14052 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
14053 {
14054         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
14055                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
14056         MonoBoolean result = FALSE;
14057         guint32 flags;
14058
14059         /* quick exit if no declarative security is present in the metadata */
14060         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14061                 return FALSE;
14062
14063         /* we want the original as the wrapper is "free" of the security informations */
14064         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14065                 method = mono_marshal_method_from_wrapper (method);
14066                 if (!method)
14067                         return FALSE;
14068         }
14069
14070         /* First we look for method-level attributes */
14071         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14072                 mono_class_init (method->klass);
14073                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14074
14075                 result = mono_declsec_get_method_demands_params (method, demands, 
14076                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14077         }
14078
14079         /* Here we use (or create) the class declarative cache to look for demands */
14080         flags = mono_declsec_flags_from_class (method->klass);
14081         if (flags & mask) {
14082                 if (!result) {
14083                         mono_class_init (method->klass);
14084                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
14085                 }
14086                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
14087                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
14088         }
14089
14090         /* The boolean return value is used as a shortcut in case nothing needs to
14091            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
14092         return result;
14093 }
14094
14095
14096 /*
14097  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
14098  *
14099  * Note: Don't use the content of actions if the function return FALSE.
14100  */
14101 MonoBoolean
14102 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
14103 {
14104         MonoBoolean result = FALSE;
14105         guint32 flags;
14106
14107         /* quick exit if no declarative security is present in the metadata */
14108         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14109                 return FALSE;
14110
14111         /* we want the original as the wrapper is "free" of the security informations */
14112         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14113                 method = mono_marshal_method_from_wrapper (method);
14114                 if (!method)
14115                         return FALSE;
14116         }
14117
14118         /* results are independant - zeroize both */
14119         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
14120         memset (klass, 0, sizeof (MonoDeclSecurityActions));
14121
14122         /* First we look for method-level attributes */
14123         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14124                 mono_class_init (method->klass);
14125
14126                 result = mono_declsec_get_method_demands_params (method, cmethod, 
14127                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14128         }
14129
14130         /* Here we use (or create) the class declarative cache to look for demands */
14131         flags = mono_declsec_flags_from_class (method->klass);
14132         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
14133                 mono_class_init (method->klass);
14134
14135                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
14136                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
14137         }
14138
14139         return result;
14140 }
14141
14142 /*
14143  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14144  *
14145  * @klass       The inherited class - this is the class that provides the security check (attributes)
14146  * @demans      
14147  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
14148  * 
14149  * Note: Don't use the content of actions if the function return FALSE.
14150  */
14151 MonoBoolean
14152 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
14153 {
14154         MonoBoolean result = FALSE;
14155         guint32 flags;
14156
14157         /* quick exit if no declarative security is present in the metadata */
14158         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14159                 return FALSE;
14160
14161         /* Here we use (or create) the class declarative cache to look for demands */
14162         flags = mono_declsec_flags_from_class (klass);
14163         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
14164                 mono_class_init (klass);
14165                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14166
14167                 result |= mono_declsec_get_class_demands_params (klass, demands, 
14168                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14169         }
14170
14171         return result;
14172 }
14173
14174 /*
14175  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
14176  *
14177  * Note: Don't use the content of actions if the function return FALSE.
14178  */
14179 MonoBoolean
14180 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
14181 {
14182         /* quick exit if no declarative security is present in the metadata */
14183         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
14184                 return FALSE;
14185
14186         /* we want the original as the wrapper is "free" of the security informations */
14187         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
14188                 method = mono_marshal_method_from_wrapper (method);
14189                 if (!method)
14190                         return FALSE;
14191         }
14192
14193         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14194                 mono_class_init (method->klass);
14195                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
14196
14197                 return mono_declsec_get_method_demands_params (method, demands, 
14198                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
14199         }
14200         return FALSE;
14201 }
14202
14203
14204 static MonoBoolean
14205 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
14206 {
14207         guint32 cols [MONO_DECL_SECURITY_SIZE];
14208         MonoTableInfo *t;
14209         int i;
14210
14211         int index = mono_metadata_declsec_from_index (image, token);
14212         if (index == -1)
14213                 return FALSE;
14214
14215         t =  &image->tables [MONO_TABLE_DECLSECURITY];
14216         for (i = index; i < t->rows; i++) {
14217                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
14218
14219                 /* shortcut - index are ordered */
14220                 if (token != cols [MONO_DECL_SECURITY_PARENT])
14221                         return FALSE;
14222
14223                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
14224                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
14225                         entry->blob = (char*) (metadata + 2);
14226                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
14227                         return TRUE;
14228                 }
14229         }
14230
14231         return FALSE;
14232 }
14233
14234 MonoBoolean
14235 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
14236 {
14237         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
14238                 guint32 idx = mono_method_get_index (method);
14239                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14240                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
14241                 return get_declsec_action (method->klass->image, idx, action, entry);
14242         }
14243         return FALSE;
14244 }
14245
14246 MonoBoolean
14247 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
14248 {
14249         /* use cache */
14250         guint32 flags = mono_declsec_flags_from_class (klass);
14251         if (declsec_flags_map [action] & flags) {
14252                 guint32 idx = mono_metadata_token_index (klass->type_token);
14253                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
14254                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
14255                 return get_declsec_action (klass->image, idx, action, entry);
14256         }
14257         return FALSE;
14258 }
14259
14260 MonoBoolean
14261 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
14262 {
14263         guint32 idx = 1; /* there is only one assembly */
14264         idx <<= MONO_HAS_DECL_SECURITY_BITS;
14265         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
14266
14267         return get_declsec_action (assembly->image, idx, action, entry);
14268 }
14269
14270 gboolean
14271 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
14272 {
14273         MonoError error;
14274         MonoObject *res, *exc;
14275         void *params [1];
14276         static MonoMethod *method = NULL;
14277
14278         if (method == NULL) {
14279                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
14280                 g_assert (method);
14281         }
14282
14283         /* 
14284          * The result of mono_type_get_object_checked () might be a System.MonoType but we
14285          * need a TypeBuilder so use mono_class_get_ref_info (klass).
14286          */
14287         g_assert (mono_class_get_ref_info (klass));
14288         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
14289
14290         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
14291         mono_error_raise_exception (&error); /* FIXME don't raise here */
14292
14293         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
14294
14295         if (exc || !mono_error_ok (&error)) {
14296                 mono_error_cleanup (&error);
14297                 return FALSE;
14298         } else
14299                 return *(MonoBoolean*)mono_object_unbox (res);
14300 }
14301
14302 /**
14303  * mono_reflection_type_get_type:
14304  * @reftype: the System.Type object
14305  *
14306  * Returns the MonoType* associated with the C# System.Type object @reftype.
14307  */
14308 MonoType*
14309 mono_reflection_type_get_type (MonoReflectionType *reftype)
14310 {
14311         g_assert (reftype);
14312
14313         MonoError error;
14314         MonoType *result = mono_reflection_type_get_handle (reftype, &error);
14315         mono_error_assert_ok (&error);
14316         return result;
14317 }
14318
14319 /**
14320  * mono_reflection_assembly_get_assembly:
14321  * @refassembly: the System.Reflection.Assembly object
14322  *
14323  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
14324  */
14325 MonoAssembly*
14326 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
14327 {
14328         g_assert (refassembly);
14329
14330         return refassembly->assembly;
14331 }
14332