Merge pull request #2675 from lambdageek/dev/monoerror-mono_string_intern
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2011 Rodrigo Kumpera
10  *
11  */
12 #include <config.h>
13 #include "mono/utils/mono-digest.h"
14 #include "mono/utils/mono-membar.h"
15 #include "mono/metadata/reflection-internals.h"
16 #include "mono/metadata/tabledefs.h"
17 #include "mono/metadata/metadata-internals.h"
18 #include <mono/metadata/profiler-private.h>
19 #include "mono/metadata/class-internals.h"
20 #include "mono/metadata/gc-internals.h"
21 #include "mono/metadata/tokentype.h"
22 #include "mono/metadata/domain-internals.h"
23 #include "mono/metadata/opcodes.h"
24 #include "mono/metadata/assembly.h"
25 #include "mono/metadata/object-internals.h"
26 #include <mono/metadata/exception.h>
27 #include <mono/metadata/marshal.h>
28 #include <mono/metadata/security-manager.h>
29 #include <stdio.h>
30 #include <glib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <string.h>
34 #include <ctype.h>
35 #include "image.h"
36 #include "cil-coff.h"
37 #include "mono-endian.h"
38 #include <mono/metadata/gc-internals.h>
39 #include <mono/metadata/mempool-internals.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include <mono/metadata/verify-internals.h>
43 #include <mono/metadata/mono-ptr-array.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/checked-build.h>
47
48 static gboolean is_usertype (MonoReflectionType *ref);
49 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error);
50
51 typedef struct {
52         char *p;
53         char *buf;
54         char *end;
55 } SigBuffer;
56
57 #define TEXT_OFFSET 512
58 #define CLI_H_SIZE 136
59 #define FILE_ALIGN 512
60 #define VIRT_ALIGN 8192
61 #define START_TEXT_RVA  0x00002000
62
63 typedef struct {
64         MonoReflectionILGen *ilgen;
65         MonoReflectionType *rtype;
66         MonoArray *parameters;
67         MonoArray *generic_params;
68         MonoGenericContainer *generic_container;
69         MonoArray *pinfo;
70         MonoArray *opt_types;
71         guint32 attrs;
72         guint32 iattrs;
73         guint32 call_conv;
74         guint32 *table_idx; /* note: it's a pointer */
75         MonoArray *code;
76         MonoObject *type;
77         MonoString *name;
78         MonoBoolean init_locals;
79         MonoBoolean skip_visibility;
80         MonoArray *return_modreq;
81         MonoArray *return_modopt;
82         MonoArray *param_modreq;
83         MonoArray *param_modopt;
84         MonoArray *permissions;
85         MonoMethod *mhandle;
86         guint32 nrefs;
87         gpointer *refs;
88         /* for PInvoke */
89         int charset, extra_flags, native_cc;
90         MonoString *dll, *dllentry;
91 } ReflectionMethodBuilder;
92
93 typedef struct {
94         guint32 owner;
95         MonoReflectionGenericParam *gparam;
96 } GenericParamTableEntry;
97
98 const unsigned char table_sizes [MONO_TABLE_NUM] = {
99         MONO_MODULE_SIZE,
100         MONO_TYPEREF_SIZE,
101         MONO_TYPEDEF_SIZE,
102         0,
103         MONO_FIELD_SIZE,
104         0,
105         MONO_METHOD_SIZE,
106         0,
107         MONO_PARAM_SIZE,
108         MONO_INTERFACEIMPL_SIZE,
109         MONO_MEMBERREF_SIZE,    /* 0x0A */
110         MONO_CONSTANT_SIZE,
111         MONO_CUSTOM_ATTR_SIZE,
112         MONO_FIELD_MARSHAL_SIZE,
113         MONO_DECL_SECURITY_SIZE,
114         MONO_CLASS_LAYOUT_SIZE,
115         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
116         MONO_STAND_ALONE_SIGNATURE_SIZE,
117         MONO_EVENT_MAP_SIZE,
118         0,
119         MONO_EVENT_SIZE,
120         MONO_PROPERTY_MAP_SIZE,
121         0,
122         MONO_PROPERTY_SIZE,
123         MONO_METHOD_SEMA_SIZE,
124         MONO_METHODIMPL_SIZE,
125         MONO_MODULEREF_SIZE,    /* 0x1A */
126         MONO_TYPESPEC_SIZE,
127         MONO_IMPLMAP_SIZE,      
128         MONO_FIELD_RVA_SIZE,
129         0,
130         0,
131         MONO_ASSEMBLY_SIZE,     /* 0x20 */
132         MONO_ASSEMBLY_PROCESSOR_SIZE,
133         MONO_ASSEMBLYOS_SIZE,
134         MONO_ASSEMBLYREF_SIZE,
135         MONO_ASSEMBLYREFPROC_SIZE,
136         MONO_ASSEMBLYREFOS_SIZE,
137         MONO_FILE_SIZE,
138         MONO_EXP_TYPE_SIZE,
139         MONO_MANIFEST_SIZE,
140         MONO_NESTED_CLASS_SIZE,
141
142         MONO_GENERICPARAM_SIZE, /* 0x2A */
143         MONO_METHODSPEC_SIZE,
144         MONO_GENPARCONSTRAINT_SIZE
145
146 };
147
148 #ifndef DISABLE_REFLECTION_EMIT
149 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
150 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_open_instance, MonoError *error);
151 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb, MonoError *error);
152 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
153 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError  *error);
154 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
155 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error);
156 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
157 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
158 static gboolean reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error);
159 static gboolean reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error);
160 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
161 #endif
162
163 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
164 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
165 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
166 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
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) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
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 #ifndef DISABLE_REFLECTION_EMIT
428 static char*
429 image_strdup (MonoImage *image, const char *s)
430 {
431         MONO_REQ_GC_NEUTRAL_MODE;
432
433         if (image)
434                 return mono_image_strdup (image, s);
435         else
436                 return g_strdup (s);
437 }
438 #endif
439
440 #define image_g_new(image,struct_type, n_structs)               \
441     ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
442
443 #define image_g_new0(image,struct_type, n_structs)              \
444     ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
445
446
447 static void
448 alloc_table (MonoDynamicTable *table, guint nrows)
449 {
450         MONO_REQ_GC_NEUTRAL_MODE;
451
452         table->rows = nrows;
453         g_assert (table->columns);
454         if (nrows + 1 >= table->alloc_rows) {
455                 while (nrows + 1 >= table->alloc_rows) {
456                         if (table->alloc_rows == 0)
457                                 table->alloc_rows = 16;
458                         else
459                                 table->alloc_rows *= 2;
460                 }
461
462                 table->values = (guint32 *)g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
463         }
464 }
465
466 static void
467 make_room_in_stream (MonoDynamicStream *stream, int size)
468 {
469         MONO_REQ_GC_NEUTRAL_MODE;
470
471         if (size <= stream->alloc_size)
472                 return;
473         
474         while (stream->alloc_size <= size) {
475                 if (stream->alloc_size < 4096)
476                         stream->alloc_size = 4096;
477                 else
478                         stream->alloc_size *= 2;
479         }
480         
481         stream->data = (char *)g_realloc (stream->data, stream->alloc_size);
482 }
483
484 static guint32
485 string_heap_insert (MonoDynamicStream *sh, const char *str)
486 {
487         MONO_REQ_GC_NEUTRAL_MODE;
488
489         guint32 idx;
490         guint32 len;
491         gpointer oldkey, oldval;
492
493         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
494                 return GPOINTER_TO_UINT (oldval);
495
496         len = strlen (str) + 1;
497         idx = sh->index;
498         
499         make_room_in_stream (sh, idx + len);
500
501         /*
502          * We strdup the string even if we already copy them in sh->data
503          * so that the string pointers in the hash remain valid even if
504          * we need to realloc sh->data. We may want to avoid that later.
505          */
506         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
507         memcpy (sh->data + idx, str, len);
508         sh->index += len;
509         return idx;
510 }
511
512 static guint32
513 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
514 {
515         MONO_REQ_GC_UNSAFE_MODE;
516
517         char *name = mono_string_to_utf8 (str);
518         guint32 idx;
519         idx = string_heap_insert (sh, name);
520         g_free (name);
521         return idx;
522 }
523
524 #ifndef DISABLE_REFLECTION_EMIT
525 static void
526 string_heap_init (MonoDynamicStream *sh)
527 {
528         MONO_REQ_GC_NEUTRAL_MODE;
529
530         sh->index = 0;
531         sh->alloc_size = 4096;
532         sh->data = (char *)g_malloc (4096);
533         sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
534         string_heap_insert (sh, "");
535 }
536 #endif
537
538 static guint32
539 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
540 {
541         MONO_REQ_GC_NEUTRAL_MODE;
542
543         guint32 idx;
544         
545         make_room_in_stream (stream, stream->index + len);
546         memcpy (stream->data + stream->index, data, len);
547         idx = stream->index;
548         stream->index += len;
549         /* 
550          * align index? Not without adding an additional param that controls it since
551          * we may store a blob value in pieces.
552          */
553         return idx;
554 }
555
556 static guint32
557 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
558 {
559         MONO_REQ_GC_NEUTRAL_MODE;
560
561         guint32 idx;
562         
563         make_room_in_stream (stream, stream->index + len);
564         memset (stream->data + stream->index, 0, len);
565         idx = stream->index;
566         stream->index += len;
567         return idx;
568 }
569
570 static void
571 stream_data_align (MonoDynamicStream *stream)
572 {
573         MONO_REQ_GC_NEUTRAL_MODE;
574
575         char buf [4] = {0};
576         guint32 count = stream->index % 4;
577
578         /* we assume the stream data will be aligned */
579         if (count)
580                 mono_image_add_stream_data (stream, buf, 4 - count);
581 }
582
583 #ifndef DISABLE_REFLECTION_EMIT
584 static int
585 mono_blob_entry_hash (const char* str)
586 {
587         MONO_REQ_GC_NEUTRAL_MODE;
588
589         guint len, h;
590         const char *end;
591         len = mono_metadata_decode_blob_size (str, &str);
592         if (len > 0) {
593                 end = str + len;
594                 h = *str;
595                 for (str += 1; str < end; str++)
596                         h = (h << 5) - h + *str;
597                 return h;
598         } else {
599                 return 0;
600         }
601 }
602
603 static gboolean
604 mono_blob_entry_equal (const char *str1, const char *str2) {
605         MONO_REQ_GC_NEUTRAL_MODE;
606
607         int len, len2;
608         const char *end1;
609         const char *end2;
610         len = mono_metadata_decode_blob_size (str1, &end1);
611         len2 = mono_metadata_decode_blob_size (str2, &end2);
612         if (len != len2)
613                 return 0;
614         return memcmp (end1, end2, len) == 0;
615 }
616 #endif
617 static guint32
618 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
619 {
620         MONO_REQ_GC_NEUTRAL_MODE;
621
622         guint32 idx;
623         char *copy;
624         gpointer oldkey, oldval;
625
626         copy = (char *)g_malloc (s1+s2);
627         memcpy (copy, b1, s1);
628         memcpy (copy + s1, b2, s2);
629         if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
630                 g_free (copy);
631                 idx = GPOINTER_TO_UINT (oldval);
632         } else {
633                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
634                 mono_image_add_stream_data (&assembly->blob, b2, s2);
635                 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
636         }
637         return idx;
638 }
639
640 static guint32
641 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
642 {
643         MONO_REQ_GC_NEUTRAL_MODE;
644
645         char blob_size [8];
646         char *b = blob_size;
647         guint32 size = buf->p - buf->buf;
648         /* store length */
649         g_assert (size <= (buf->end - buf->buf));
650         mono_metadata_encode_value (size, b, &b);
651         return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
652 }
653
654 /*
655  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
656  * dest may be misaligned.
657  */
658 static void
659 swap_with_size (char *dest, const char* val, int len, int nelem) {
660         MONO_REQ_GC_NEUTRAL_MODE;
661 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
662         int elem;
663
664         for (elem = 0; elem < nelem; ++elem) {
665                 switch (len) {
666                 case 1:
667                         *dest = *val;
668                         break;
669                 case 2:
670                         dest [0] = val [1];
671                         dest [1] = val [0];
672                         break;
673                 case 4:
674                         dest [0] = val [3];
675                         dest [1] = val [2];
676                         dest [2] = val [1];
677                         dest [3] = val [0];
678                         break;
679                 case 8:
680                         dest [0] = val [7];
681                         dest [1] = val [6];
682                         dest [2] = val [5];
683                         dest [3] = val [4];
684                         dest [4] = val [3];
685                         dest [5] = val [2];
686                         dest [6] = val [1];
687                         dest [7] = val [0];
688                         break;
689                 default:
690                         g_assert_not_reached ();
691                 }
692                 dest += len;
693                 val += len;
694         }
695 #else
696         memcpy (dest, val, len * nelem);
697 #endif
698 }
699
700 static guint32
701 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
702 {
703         MONO_REQ_GC_UNSAFE_MODE;
704         
705         char blob_size [64];
706         char *b = blob_size;
707         guint32 idx = 0, len;
708
709         len = str->length * 2;
710         mono_metadata_encode_value (len, b, &b);
711 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
712         {
713                 char *swapped = g_malloc (2 * mono_string_length (str));
714                 const char *p = (const char*)mono_string_chars (str);
715
716                 swap_with_size (swapped, p, 2, mono_string_length (str));
717                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
718                 g_free (swapped);
719         }
720 #else
721         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
722 #endif
723         return idx;
724 }
725
726 #ifndef DISABLE_REFLECTION_EMIT
727 static MonoClass *
728 default_class_from_mono_type (MonoType *type)
729 {
730         MONO_REQ_GC_NEUTRAL_MODE;
731
732         switch (type->type) {
733         case MONO_TYPE_OBJECT:
734                 return mono_defaults.object_class;
735         case MONO_TYPE_VOID:
736                 return mono_defaults.void_class;
737         case MONO_TYPE_BOOLEAN:
738                 return mono_defaults.boolean_class;
739         case MONO_TYPE_CHAR:
740                 return mono_defaults.char_class;
741         case MONO_TYPE_I1:
742                 return mono_defaults.sbyte_class;
743         case MONO_TYPE_U1:
744                 return mono_defaults.byte_class;
745         case MONO_TYPE_I2:
746                 return mono_defaults.int16_class;
747         case MONO_TYPE_U2:
748                 return mono_defaults.uint16_class;
749         case MONO_TYPE_I4:
750                 return mono_defaults.int32_class;
751         case MONO_TYPE_U4:
752                 return mono_defaults.uint32_class;
753         case MONO_TYPE_I:
754                 return mono_defaults.int_class;
755         case MONO_TYPE_U:
756                 return mono_defaults.uint_class;
757         case MONO_TYPE_I8:
758                 return mono_defaults.int64_class;
759         case MONO_TYPE_U8:
760                 return mono_defaults.uint64_class;
761         case MONO_TYPE_R4:
762                 return mono_defaults.single_class;
763         case MONO_TYPE_R8:
764                 return mono_defaults.double_class;
765         case MONO_TYPE_STRING:
766                 return mono_defaults.string_class;
767         default:
768                 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
769                 g_assert_not_reached ();
770         }
771         
772         return NULL;
773 }
774 #endif
775
776 /*
777  * mono_class_get_ref_info:
778  *
779  *   Return the type builder/generic param builder corresponding to KLASS, if it exists.
780  */
781 gpointer
782 mono_class_get_ref_info (MonoClass *klass)
783 {
784         MONO_REQ_GC_UNSAFE_MODE;
785
786         if (klass->ref_info_handle == 0)
787                 return NULL;
788         else
789                 return mono_gchandle_get_target (klass->ref_info_handle);
790 }
791
792 void
793 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
794 {
795         MONO_REQ_GC_UNSAFE_MODE;
796
797         klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
798         g_assert (klass->ref_info_handle != 0);
799 }
800
801 void
802 mono_class_free_ref_info (MonoClass *klass)
803 {
804         MONO_REQ_GC_NEUTRAL_MODE;
805
806         if (klass->ref_info_handle) {
807                 mono_gchandle_free (klass->ref_info_handle);
808                 klass->ref_info_handle = 0;
809         }
810 }
811
812 static void
813 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
814 {
815         MONO_REQ_GC_NEUTRAL_MODE;
816
817         int i;
818         MonoGenericInst *class_inst;
819         MonoClass *klass;
820
821         g_assert (gclass);
822
823         class_inst = gclass->context.class_inst;
824
825         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
826         klass = gclass->container_class;
827         sigbuffer_add_value (buf, klass->byval_arg.type);
828         sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
829
830         sigbuffer_add_value (buf, class_inst->type_argc);
831         for (i = 0; i < class_inst->type_argc; ++i)
832                 encode_type (assembly, class_inst->type_argv [i], buf);
833
834 }
835
836 static void
837 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
838 {
839         MONO_REQ_GC_NEUTRAL_MODE;
840
841         if (!type) {
842                 g_assert_not_reached ();
843                 return;
844         }
845                 
846         if (type->byref)
847                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
848
849         switch (type->type){
850         case MONO_TYPE_VOID:
851         case MONO_TYPE_BOOLEAN:
852         case MONO_TYPE_CHAR:
853         case MONO_TYPE_I1:
854         case MONO_TYPE_U1:
855         case MONO_TYPE_I2:
856         case MONO_TYPE_U2:
857         case MONO_TYPE_I4:
858         case MONO_TYPE_U4:
859         case MONO_TYPE_I8:
860         case MONO_TYPE_U8:
861         case MONO_TYPE_R4:
862         case MONO_TYPE_R8:
863         case MONO_TYPE_I:
864         case MONO_TYPE_U:
865         case MONO_TYPE_STRING:
866         case MONO_TYPE_OBJECT:
867         case MONO_TYPE_TYPEDBYREF:
868                 sigbuffer_add_value (buf, type->type);
869                 break;
870         case MONO_TYPE_PTR:
871                 sigbuffer_add_value (buf, type->type);
872                 encode_type (assembly, type->data.type, buf);
873                 break;
874         case MONO_TYPE_SZARRAY:
875                 sigbuffer_add_value (buf, type->type);
876                 encode_type (assembly, &type->data.klass->byval_arg, buf);
877                 break;
878         case MONO_TYPE_VALUETYPE:
879         case MONO_TYPE_CLASS: {
880                 MonoClass *k = mono_class_from_mono_type (type);
881
882                 if (k->generic_container) {
883                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
884                         encode_generic_class (assembly, gclass, buf);
885                 } else {
886                         /*
887                          * Make sure we use the correct type.
888                          */
889                         sigbuffer_add_value (buf, k->byval_arg.type);
890                         /*
891                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
892                          * otherwise two typerefs could point to the same type, leading to
893                          * verification errors.
894                          */
895                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
896                 }
897                 break;
898         }
899         case MONO_TYPE_ARRAY:
900                 sigbuffer_add_value (buf, type->type);
901                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
902                 sigbuffer_add_value (buf, type->data.array->rank);
903                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
904                 sigbuffer_add_value (buf, 0);
905                 break;
906         case MONO_TYPE_GENERICINST:
907                 encode_generic_class (assembly, type->data.generic_class, buf);
908                 break;
909         case MONO_TYPE_VAR:
910         case MONO_TYPE_MVAR:
911                 sigbuffer_add_value (buf, type->type);
912                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
913                 break;
914         default:
915                 g_error ("need to encode type %x", type->type);
916         }
917 }
918
919 static void
920 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
921 {
922         MONO_REQ_GC_UNSAFE_MODE;
923
924         if (!type) {
925                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
926                 return;
927         }
928
929         encode_type (assembly, mono_reflection_type_get_handle (type), buf);
930 }
931
932 static void
933 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
934 {
935         MONO_REQ_GC_UNSAFE_MODE;
936
937         int i;
938
939         if (modreq) {
940                 for (i = 0; i < mono_array_length (modreq); ++i) {
941                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
942                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
943                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
944                 }
945         }
946         if (modopt) {
947                 for (i = 0; i < mono_array_length (modopt); ++i) {
948                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
949                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
950                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
951                 }
952         }
953 }
954
955 #ifndef DISABLE_REFLECTION_EMIT
956 static guint32
957 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
958 {
959         MONO_REQ_GC_UNSAFE_MODE;
960
961         SigBuffer buf;
962         int i;
963         guint32 nparams =  sig->param_count;
964         guint32 idx;
965
966         if (!assembly->save)
967                 return 0;
968
969         sigbuffer_init (&buf, 32);
970         /*
971          * FIXME: vararg, explicit_this, differenc call_conv values...
972          */
973         idx = sig->call_convention;
974         if (sig->hasthis)
975                 idx |= 0x20; /* hasthis */
976         if (sig->generic_param_count)
977                 idx |= 0x10; /* generic */
978         sigbuffer_add_byte (&buf, idx);
979         if (sig->generic_param_count)
980                 sigbuffer_add_value (&buf, sig->generic_param_count);
981         sigbuffer_add_value (&buf, nparams);
982         encode_type (assembly, sig->ret, &buf);
983         for (i = 0; i < nparams; ++i) {
984                 if (i == sig->sentinelpos)
985                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
986                 encode_type (assembly, sig->params [i], &buf);
987         }
988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
989         sigbuffer_free (&buf);
990         return idx;
991 }
992 #endif
993
994 static guint32
995 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
996 {
997         MONO_REQ_GC_UNSAFE_MODE;
998
999         /*
1000          * FIXME: reuse code from method_encode_signature().
1001          */
1002         SigBuffer buf;
1003         int i;
1004         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
1005         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
1006         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
1007         guint32 idx;
1008
1009         sigbuffer_init (&buf, 32);
1010         /* LAMESPEC: all the call conv spec is foobared */
1011         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
1012         if (mb->call_conv & 2)
1013                 idx |= 0x5; /* vararg */
1014         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
1015                 idx |= 0x20; /* hasthis */
1016         if (ngparams)
1017                 idx |= 0x10; /* generic */
1018         sigbuffer_add_byte (&buf, idx);
1019         if (ngparams)
1020                 sigbuffer_add_value (&buf, ngparams);
1021         sigbuffer_add_value (&buf, nparams + notypes);
1022         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
1023         encode_reflection_type (assembly, mb->rtype, &buf);
1024         for (i = 0; i < nparams; ++i) {
1025                 MonoArray *modreq = NULL;
1026                 MonoArray *modopt = NULL;
1027                 MonoReflectionType *pt;
1028
1029                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
1030                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
1031                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
1032                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
1033                 encode_custom_modifiers (assembly, modreq, modopt, &buf);
1034                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1035                 encode_reflection_type (assembly, pt, &buf);
1036         }
1037         if (notypes)
1038                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
1039         for (i = 0; i < notypes; ++i) {
1040                 MonoReflectionType *pt;
1041
1042                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
1043                 encode_reflection_type (assembly, pt, &buf);
1044         }
1045
1046         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1047         sigbuffer_free (&buf);
1048         return idx;
1049 }
1050
1051 static guint32
1052 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
1053 {
1054         MONO_REQ_GC_UNSAFE_MODE;
1055
1056         MonoDynamicTable *table;
1057         guint32 *values;
1058         guint32 idx, sig_idx;
1059         guint nl = mono_array_length (ilgen->locals);
1060         SigBuffer buf;
1061         int i;
1062
1063         sigbuffer_init (&buf, 32);
1064         sigbuffer_add_value (&buf, 0x07);
1065         sigbuffer_add_value (&buf, nl);
1066         for (i = 0; i < nl; ++i) {
1067                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
1068                 
1069                 if (lb->is_pinned)
1070                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
1071                 
1072                 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
1073         }
1074         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1075         sigbuffer_free (&buf);
1076
1077         if (assembly->standalonesig_cache == NULL)
1078                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
1079         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
1080         if (idx)
1081                 return idx;
1082
1083         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
1084         idx = table->next_idx ++;
1085         table->rows ++;
1086         alloc_table (table, table->rows);
1087         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
1088
1089         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
1090
1091         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
1092
1093         return idx;
1094 }
1095
1096 static guint32
1097 method_count_clauses (MonoReflectionILGen *ilgen)
1098 {
1099         MONO_REQ_GC_UNSAFE_MODE;
1100
1101         guint32 num_clauses = 0;
1102         int i;
1103
1104         MonoILExceptionInfo *ex_info;
1105         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
1106                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1107                 if (ex_info->handlers)
1108                         num_clauses += mono_array_length (ex_info->handlers);
1109                 else
1110                         num_clauses++;
1111         }
1112
1113         return num_clauses;
1114 }
1115
1116 #ifndef DISABLE_REFLECTION_EMIT
1117 static MonoExceptionClause*
1118 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
1119 {
1120         MONO_REQ_GC_UNSAFE_MODE;
1121
1122         MonoExceptionClause *clauses;
1123         MonoExceptionClause *clause;
1124         MonoILExceptionInfo *ex_info;
1125         MonoILExceptionBlock *ex_block;
1126         guint32 finally_start;
1127         int i, j, clause_index;;
1128
1129         clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
1130
1131         clause_index = 0;
1132         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
1133                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
1134                 finally_start = ex_info->start + ex_info->len;
1135                 if (!ex_info->handlers)
1136                         continue;
1137                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1138                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1139                         clause = &(clauses [clause_index]);
1140
1141                         clause->flags = ex_block->type;
1142                         clause->try_offset = ex_info->start;
1143
1144                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1145                                 clause->try_len = finally_start - ex_info->start;
1146                         else
1147                                 clause->try_len = ex_info->len;
1148                         clause->handler_offset = ex_block->start;
1149                         clause->handler_len = ex_block->len;
1150                         if (ex_block->extype) {
1151                                 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
1152                         } else {
1153                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1154                                         clause->data.filter_offset = ex_block->filter_offset;
1155                                 else
1156                                         clause->data.filter_offset = 0;
1157                         }
1158                         finally_start = ex_block->start + ex_block->len;
1159
1160                         clause_index ++;
1161                 }
1162         }
1163
1164         return clauses;
1165 }
1166 #endif /* !DISABLE_REFLECTION_EMIT */
1167
1168 /**
1169  * method_encode_code:
1170  *
1171  * @assembly the assembly
1172  * @mb the managed MethodBuilder
1173  * @error set on error
1174  *
1175  * Note that the return value is not sensible if @error is set.
1176  */
1177 static guint32
1178 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
1179 {
1180         MONO_REQ_GC_UNSAFE_MODE;
1181
1182         char flags = 0;
1183         guint32 idx;
1184         guint32 code_size;
1185         gint32 max_stack, i;
1186         gint32 num_locals = 0;
1187         gint32 num_exception = 0;
1188         gint maybe_small;
1189         guint32 fat_flags;
1190         char fat_header [12];
1191         guint32 int_value;
1192         guint16 short_value;
1193         guint32 local_sig = 0;
1194         guint32 header_size = 12;
1195         MonoArray *code;
1196
1197         mono_error_init (error);
1198
1199         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1200                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1201                 return 0;
1202
1203         /*if (mb->name)
1204                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1205         if (mb->ilgen) {
1206                 code = mb->ilgen->code;
1207                 code_size = mb->ilgen->code_len;
1208                 max_stack = mb->ilgen->max_stack;
1209                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1210                 if (mb->ilgen->ex_handlers)
1211                         num_exception = method_count_clauses (mb->ilgen);
1212         } else {
1213                 code = mb->code;
1214                 if (code == NULL){
1215                         char *name = mono_string_to_utf8 (mb->name);
1216                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1217                         mono_error_set_argument (error, NULL, "a method does not have any IL associated");
1218                         g_free (str);
1219                         g_free (name);
1220                         return 0;
1221                 }
1222
1223                 code_size = mono_array_length (code);
1224                 max_stack = 8; /* we probably need to run a verifier on the code... */
1225         }
1226
1227         stream_data_align (&assembly->code);
1228
1229         /* check for exceptions, maxstack, locals */
1230         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1231         if (maybe_small) {
1232                 if (code_size < 64 && !(code_size & 1)) {
1233                         flags = (code_size << 2) | 0x2;
1234                 } else if (code_size < 32 && (code_size & 1)) {
1235                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1236                 } else {
1237                         goto fat_header;
1238                 }
1239                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1240                 /* add to the fixup todo list */
1241                 if (mb->ilgen && mb->ilgen->num_token_fixups)
1242                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1243                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1244                 return assembly->text_rva + idx;
1245         } 
1246 fat_header:
1247         if (num_locals)
1248                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1249         /* 
1250          * FIXME: need to set also the header size in fat_flags.
1251          * (and more sects and init locals flags)
1252          */
1253         fat_flags =  0x03;
1254         if (num_exception)
1255                 fat_flags |= METHOD_HEADER_MORE_SECTS;
1256         if (mb->init_locals)
1257                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1258         fat_header [0] = fat_flags;
1259         fat_header [1] = (header_size / 4 ) << 4;
1260         short_value = GUINT16_TO_LE (max_stack);
1261         memcpy (fat_header + 2, &short_value, 2);
1262         int_value = GUINT32_TO_LE (code_size);
1263         memcpy (fat_header + 4, &int_value, 4);
1264         int_value = GUINT32_TO_LE (local_sig);
1265         memcpy (fat_header + 8, &int_value, 4);
1266         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1267         /* add to the fixup todo list */
1268         if (mb->ilgen && mb->ilgen->num_token_fixups)
1269                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1270         
1271         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1272         if (num_exception) {
1273                 unsigned char sheader [4];
1274                 MonoILExceptionInfo * ex_info;
1275                 MonoILExceptionBlock * ex_block;
1276                 int j;
1277
1278                 stream_data_align (&assembly->code);
1279                 /* always use fat format for now */
1280                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1281                 num_exception *= 6 * sizeof (guint32);
1282                 num_exception += 4; /* include the size of the header */
1283                 sheader [1] = num_exception & 0xff;
1284                 sheader [2] = (num_exception >> 8) & 0xff;
1285                 sheader [3] = (num_exception >> 16) & 0xff;
1286                 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1287                 /* fat header, so we are already aligned */
1288                 /* reverse order */
1289                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1290                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1291                         if (ex_info->handlers) {
1292                                 int finally_start = ex_info->start + ex_info->len;
1293                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1294                                         guint32 val;
1295                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1296                                         /* the flags */
1297                                         val = GUINT32_TO_LE (ex_block->type);
1298                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1299                                         /* try offset */
1300                                         val = GUINT32_TO_LE (ex_info->start);
1301                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1302                                         /* need fault, too, probably */
1303                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1304                                                 val = GUINT32_TO_LE (finally_start - ex_info->start);
1305                                         else
1306                                                 val = GUINT32_TO_LE (ex_info->len);
1307                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1308                                         /* handler offset */
1309                                         val = GUINT32_TO_LE (ex_block->start);
1310                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1311                                         /* handler len */
1312                                         val = GUINT32_TO_LE (ex_block->len);
1313                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1314                                         finally_start = ex_block->start + ex_block->len;
1315                                         if (ex_block->extype) {
1316                                                 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1317                                         } else {
1318                                                 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1319                                                         val = ex_block->filter_offset;
1320                                                 else
1321                                                         val = 0;
1322                                         }
1323                                         val = GUINT32_TO_LE (val);
1324                                         mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1325                                         /*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", 
1326                                                         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);*/
1327                                 }
1328                         } else {
1329                                 g_error ("No clauses for ex info block %d", i);
1330                         }
1331                 }
1332         }
1333         return assembly->text_rva + idx;
1334 }
1335
1336 static guint32
1337 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1338 {
1339         MONO_REQ_GC_NEUTRAL_MODE;
1340
1341         int i;
1342         MonoDynamicTable *table;
1343         guint32 *values;
1344         
1345         table = &assembly->tables [table_idx];
1346
1347         g_assert (col < table->columns);
1348
1349         values = table->values + table->columns;
1350         for (i = 1; i <= table->rows; ++i) {
1351                 if (values [col] == token)
1352                         return i;
1353                 values += table->columns;
1354         }
1355         return 0;
1356 }
1357
1358 /*
1359  * LOCKING: Acquires the loader lock. 
1360  */
1361 static MonoCustomAttrInfo*
1362 lookup_custom_attr (MonoImage *image, gpointer member)
1363 {
1364         MONO_REQ_GC_NEUTRAL_MODE;
1365
1366         MonoCustomAttrInfo* res;
1367
1368         res = (MonoCustomAttrInfo *)mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1369
1370         if (!res)
1371                 return NULL;
1372
1373         res = (MonoCustomAttrInfo *)g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1374         res->cached = 0;
1375         return res;
1376 }
1377
1378 static gboolean
1379 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1380 {
1381         MONO_REQ_GC_UNSAFE_MODE;
1382
1383         /* FIXME: Need to do more checks */
1384         if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1385                 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1386
1387                 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1388                         return FALSE;
1389         }
1390
1391         return TRUE;
1392 }
1393
1394 static MonoCustomAttrInfo*
1395 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1396 {
1397         MONO_REQ_GC_UNSAFE_MODE;
1398
1399         int i, index, count, not_visible;
1400         MonoCustomAttrInfo *ainfo;
1401         MonoReflectionCustomAttr *cattr;
1402
1403         if (!cattrs)
1404                 return NULL;
1405         /* FIXME: check in assembly the Run flag is set */
1406
1407         count = mono_array_length (cattrs);
1408
1409         /* Skip nonpublic attributes since MS.NET seems to do the same */
1410         /* FIXME: This needs to be done more globally */
1411         not_visible = 0;
1412         for (i = 0; i < count; ++i) {
1413                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1414                 if (!custom_attr_visible (image, cattr))
1415                         not_visible ++;
1416         }
1417         count -= not_visible;
1418
1419         ainfo = (MonoCustomAttrInfo *)image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1420
1421         ainfo->image = image;
1422         ainfo->num_attrs = count;
1423         ainfo->cached = alloc_img != NULL;
1424         index = 0;
1425         for (i = 0; i < count; ++i) {
1426                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1427                 if (custom_attr_visible (image, cattr)) {
1428                         unsigned char *saved = (unsigned char *)mono_image_alloc (image, mono_array_length (cattr->data));
1429                         memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1430                         ainfo->attrs [index].ctor = cattr->ctor->method;
1431                         ainfo->attrs [index].data = saved;
1432                         ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1433                         index ++;
1434                 }
1435         }
1436
1437         return ainfo;
1438 }
1439
1440 #ifndef DISABLE_REFLECTION_EMIT
1441 /*
1442  * LOCKING: Acquires the loader lock. 
1443  */
1444 static void
1445 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1446 {
1447         MONO_REQ_GC_UNSAFE_MODE;
1448
1449         MonoCustomAttrInfo *ainfo, *tmp;
1450
1451         if (!cattrs || !mono_array_length (cattrs))
1452                 return;
1453
1454         ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1455
1456         mono_loader_lock ();
1457         tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1458         if (tmp)
1459                 mono_custom_attrs_free (tmp);
1460         mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1461         mono_loader_unlock ();
1462
1463 }
1464 #endif
1465
1466 void
1467 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1468 {
1469         MONO_REQ_GC_NEUTRAL_MODE;
1470
1471         if (!ainfo->cached)
1472                 g_free (ainfo);
1473 }
1474
1475 /*
1476  * idx is the table index of the object
1477  * type is one of MONO_CUSTOM_ATTR_*
1478  */
1479 static gboolean
1480 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs, MonoError *error)
1481 {
1482         MONO_REQ_GC_UNSAFE_MODE;
1483
1484         MonoDynamicTable *table;
1485         MonoReflectionCustomAttr *cattr;
1486         guint32 *values;
1487         guint32 count, i, token;
1488         char blob_size [6];
1489         char *p = blob_size;
1490         
1491         mono_error_init (error);
1492
1493         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1494         if (!cattrs)
1495                 return TRUE;
1496         count = mono_array_length (cattrs);
1497         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1498         table->rows += count;
1499         alloc_table (table, table->rows);
1500         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1501         idx <<= MONO_CUSTOM_ATTR_BITS;
1502         idx |= type;
1503         for (i = 0; i < count; ++i) {
1504                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1505                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1506                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE, error);
1507                 if (!mono_error_ok (error)) goto fail;
1508                 type = mono_metadata_token_index (token);
1509                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1510                 switch (mono_metadata_token_table (token)) {
1511                 case MONO_TABLE_METHOD:
1512                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1513                         /*
1514                          * fixup_cattrs () needs to fix this up. We can't use image->tokens, since it contains the old token for the
1515                          * method, not the one returned by mono_image_create_token ().
1516                          */
1517                         mono_g_hash_table_insert (assembly->remapped_tokens, GUINT_TO_POINTER (token), cattr->ctor);
1518                         break;
1519                 case MONO_TABLE_MEMBERREF:
1520                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1521                         break;
1522                 default:
1523                         g_warning ("got wrong token in custom attr");
1524                         continue;
1525                 }
1526                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1527                 p = blob_size;
1528                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1529                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1530                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1531                 values += MONO_CUSTOM_ATTR_SIZE;
1532                 ++table->next_idx;
1533         }
1534
1535         return TRUE;
1536
1537 fail:
1538         return FALSE;
1539 }
1540
1541 static void
1542 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1543 {
1544         MONO_REQ_GC_UNSAFE_MODE;
1545
1546         MonoDynamicTable *table;
1547         guint32 *values;
1548         guint32 count, i, idx;
1549         MonoReflectionPermissionSet *perm;
1550
1551         if (!permissions)
1552                 return;
1553
1554         count = mono_array_length (permissions);
1555         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1556         table->rows += count;
1557         alloc_table (table, table->rows);
1558
1559         for (i = 0; i < mono_array_length (permissions); ++i) {
1560                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1561
1562                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1563
1564                 idx = mono_metadata_token_index (parent_token);
1565                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1566                 switch (mono_metadata_token_table (parent_token)) {
1567                 case MONO_TABLE_TYPEDEF:
1568                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1569                         break;
1570                 case MONO_TABLE_METHOD:
1571                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1572                         break;
1573                 case MONO_TABLE_ASSEMBLY:
1574                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1575                         break;
1576                 default:
1577                         g_assert_not_reached ();
1578                 }
1579
1580                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1581                 values [MONO_DECL_SECURITY_PARENT] = idx;
1582                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1583
1584                 ++table->next_idx;
1585         }
1586 }
1587
1588 /*
1589  * Fill in the MethodDef and ParamDef tables for a method.
1590  * This is used for both normal methods and constructors.
1591  */
1592 static gboolean
1593 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1594 {
1595         MONO_REQ_GC_UNSAFE_MODE;
1596
1597         MonoDynamicTable *table;
1598         guint32 *values;
1599         guint i, count;
1600
1601         mono_error_init (error);
1602
1603         /* room in this table is already allocated */
1604         table = &assembly->tables [MONO_TABLE_METHOD];
1605         *mb->table_idx = table->next_idx ++;
1606         g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1607         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1608         values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1609         values [MONO_METHOD_FLAGS] = mb->attrs;
1610         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1611         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1612         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb, error);
1613         if (!mono_error_ok (error))
1614                 return FALSE;
1615
1616         table = &assembly->tables [MONO_TABLE_PARAM];
1617         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1618
1619         mono_image_add_decl_security (assembly, 
1620                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1621
1622         if (mb->pinfo) {
1623                 MonoDynamicTable *mtable;
1624                 guint32 *mvalues;
1625                 
1626                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1627                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1628                 
1629                 count = 0;
1630                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1631                         if (mono_array_get (mb->pinfo, gpointer, i))
1632                                 count++;
1633                 }
1634                 table->rows += count;
1635                 alloc_table (table, table->rows);
1636                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1637                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1638                         MonoReflectionParamBuilder *pb;
1639                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1640                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1641                                 values [MONO_PARAM_SEQUENCE] = i;
1642                                 if (pb->name != NULL) {
1643                                         values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1644                                 } else {
1645                                         values [MONO_PARAM_NAME] = 0;
1646                                 }
1647                                 values += MONO_PARAM_SIZE;
1648                                 if (pb->marshal_info) {
1649                                         mtable->rows++;
1650                                         alloc_table (mtable, mtable->rows);
1651                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1652                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1653                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1654                                 }
1655                                 pb->table_idx = table->next_idx++;
1656                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1657                                         guint32 field_type = 0;
1658                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1659                                         mtable->rows ++;
1660                                         alloc_table (mtable, mtable->rows);
1661                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1662                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1663                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1664                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1665                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1666                                 }
1667                         }
1668                 }
1669         }
1670
1671         return TRUE;
1672 }
1673
1674 #ifndef DISABLE_REFLECTION_EMIT
1675 static gboolean
1676 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
1677 {
1678         MONO_REQ_GC_UNSAFE_MODE;
1679
1680         mono_error_init (error);
1681         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1682
1683         rmb->ilgen = mb->ilgen;
1684         rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype, error);
1685         return_val_if_nok (error, FALSE);
1686         rmb->parameters = mb->parameters;
1687         rmb->generic_params = mb->generic_params;
1688         rmb->generic_container = mb->generic_container;
1689         rmb->opt_types = NULL;
1690         rmb->pinfo = mb->pinfo;
1691         rmb->attrs = mb->attrs;
1692         rmb->iattrs = mb->iattrs;
1693         rmb->call_conv = mb->call_conv;
1694         rmb->code = mb->code;
1695         rmb->type = mb->type;
1696         rmb->name = mb->name;
1697         rmb->table_idx = &mb->table_idx;
1698         rmb->init_locals = mb->init_locals;
1699         rmb->skip_visibility = FALSE;
1700         rmb->return_modreq = mb->return_modreq;
1701         rmb->return_modopt = mb->return_modopt;
1702         rmb->param_modreq = mb->param_modreq;
1703         rmb->param_modopt = mb->param_modopt;
1704         rmb->permissions = mb->permissions;
1705         rmb->mhandle = mb->mhandle;
1706         rmb->nrefs = 0;
1707         rmb->refs = NULL;
1708
1709         if (mb->dll) {
1710                 rmb->charset = mb->charset;
1711                 rmb->extra_flags = mb->extra_flags;
1712                 rmb->native_cc = mb->native_cc;
1713                 rmb->dllentry = mb->dllentry;
1714                 rmb->dll = mb->dll;
1715         }
1716
1717         return TRUE;
1718 }
1719
1720 static gboolean
1721 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
1722 {
1723         MONO_REQ_GC_UNSAFE_MODE;
1724
1725         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1726
1727         mono_error_init (error);
1728
1729         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1730
1731         rmb->ilgen = mb->ilgen;
1732         rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
1733         return_val_if_nok (error, FALSE);
1734         rmb->parameters = mb->parameters;
1735         rmb->generic_params = NULL;
1736         rmb->generic_container = NULL;
1737         rmb->opt_types = NULL;
1738         rmb->pinfo = mb->pinfo;
1739         rmb->attrs = mb->attrs;
1740         rmb->iattrs = mb->iattrs;
1741         rmb->call_conv = mb->call_conv;
1742         rmb->code = NULL;
1743         rmb->type = mb->type;
1744         rmb->name = mono_string_new (mono_domain_get (), name);
1745         rmb->table_idx = &mb->table_idx;
1746         rmb->init_locals = mb->init_locals;
1747         rmb->skip_visibility = FALSE;
1748         rmb->return_modreq = NULL;
1749         rmb->return_modopt = NULL;
1750         rmb->param_modreq = mb->param_modreq;
1751         rmb->param_modopt = mb->param_modopt;
1752         rmb->permissions = mb->permissions;
1753         rmb->mhandle = mb->mhandle;
1754         rmb->nrefs = 0;
1755         rmb->refs = NULL;
1756
1757         return TRUE;
1758 }
1759
1760 static void
1761 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1762 {
1763         MONO_REQ_GC_UNSAFE_MODE;
1764
1765         memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1766
1767         rmb->ilgen = mb->ilgen;
1768         rmb->rtype = mb->rtype;
1769         rmb->parameters = mb->parameters;
1770         rmb->generic_params = NULL;
1771         rmb->generic_container = NULL;
1772         rmb->opt_types = NULL;
1773         rmb->pinfo = NULL;
1774         rmb->attrs = mb->attrs;
1775         rmb->iattrs = 0;
1776         rmb->call_conv = mb->call_conv;
1777         rmb->code = NULL;
1778         rmb->type = (MonoObject *) mb->owner;
1779         rmb->name = mb->name;
1780         rmb->table_idx = NULL;
1781         rmb->init_locals = mb->init_locals;
1782         rmb->skip_visibility = mb->skip_visibility;
1783         rmb->return_modreq = NULL;
1784         rmb->return_modopt = NULL;
1785         rmb->param_modreq = NULL;
1786         rmb->param_modopt = NULL;
1787         rmb->permissions = NULL;
1788         rmb->mhandle = mb->mhandle;
1789         rmb->nrefs = 0;
1790         rmb->refs = NULL;
1791 }       
1792 #endif
1793
1794 static gboolean
1795 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
1796 {
1797         MONO_REQ_GC_UNSAFE_MODE;
1798
1799         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1800         MonoDynamicTable *table;
1801         guint32 *values;
1802         guint32 tok;
1803         MonoReflectionMethod *m;
1804         int i;
1805
1806         mono_error_init (error);
1807
1808         if (!mb->override_methods)
1809                 return TRUE;
1810
1811         for (i = 0; i < mono_array_length (mb->override_methods); ++i) {
1812                 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, i);
1813
1814                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1815                 table->rows ++;
1816                 alloc_table (table, table->rows);
1817                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1818                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1819                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1820
1821                 tok = mono_image_create_token (assembly, (MonoObject*)m, FALSE, FALSE, error);
1822                 return_val_if_nok (error, FALSE);
1823
1824                 switch (mono_metadata_token_table (tok)) {
1825                 case MONO_TABLE_MEMBERREF:
1826                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1827                         break;
1828                 case MONO_TABLE_METHOD:
1829                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1830                         break;
1831                 default:
1832                         g_assert_not_reached ();
1833                 }
1834                 values [MONO_METHODIMPL_DECLARATION] = tok;
1835         }
1836
1837         return TRUE;
1838 }
1839
1840 #ifndef DISABLE_REFLECTION_EMIT
1841 static gboolean
1842 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1843 {
1844         MONO_REQ_GC_UNSAFE_MODE;
1845
1846         MonoDynamicTable *table;
1847         guint32 *values;
1848         ReflectionMethodBuilder rmb;
1849         int i;
1850
1851         mono_error_init (error);
1852
1853         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error) ||
1854             !mono_image_basic_method (&rmb, assembly, error))
1855                 return FALSE;
1856
1857         mb->table_idx = *rmb.table_idx;
1858
1859         if (mb->dll) { /* It's a P/Invoke method */
1860                 guint32 moduleref;
1861                 /* map CharSet values to on-disk values */
1862                 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1863                 int extra_flags = mb->extra_flags;
1864                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1865                 table->rows ++;
1866                 alloc_table (table, table->rows);
1867                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1868                 
1869                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1870                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1871                 if (mb->dllentry)
1872                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1873                 else
1874                         values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1875                 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1876                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1877                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1878                         table->rows ++;
1879                         alloc_table (table, table->rows);
1880                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1881                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1882                 }
1883         }
1884
1885         if (mb->generic_params) {
1886                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1887                 table->rows += mono_array_length (mb->generic_params);
1888                 alloc_table (table, table->rows);
1889                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1890                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1891
1892                         mono_image_get_generic_param_info (
1893                                 (MonoReflectionGenericParam *)mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1894                 }
1895         }
1896
1897         return TRUE;
1898 }
1899
1900 static gboolean
1901 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly, MonoError *error)
1902 {
1903         MONO_REQ_GC_UNSAFE_MODE;
1904
1905         ReflectionMethodBuilder rmb;
1906
1907         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
1908                 return FALSE;
1909
1910         if (!mono_image_basic_method (&rmb, assembly, error))
1911                 return FALSE;
1912
1913         mb->table_idx = *rmb.table_idx;
1914
1915         return TRUE;
1916 }
1917 #endif
1918
1919 static char*
1920 type_get_fully_qualified_name (MonoType *type)
1921 {
1922         MONO_REQ_GC_NEUTRAL_MODE;
1923
1924         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1925 }
1926
1927 static char*
1928 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
1929 {
1930         MONO_REQ_GC_UNSAFE_MODE;
1931
1932         MonoClass *klass;
1933         MonoAssembly *ta;
1934
1935         klass = mono_class_from_mono_type (type);
1936         if (!klass) 
1937                 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1938         ta = klass->image->assembly;
1939         if (assembly_is_dynamic (ta) || (ta == ass)) {
1940                 if (klass->generic_class || klass->generic_container)
1941                         /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1942                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1943                 else
1944                         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1945         }
1946
1947         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1948 }
1949
1950 #ifndef DISABLE_REFLECTION_EMIT
1951 /*field_image is the image to which the eventual custom mods have been encoded against*/
1952 static guint32
1953 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1954 {
1955         MONO_REQ_GC_NEUTRAL_MODE;
1956
1957         SigBuffer buf;
1958         guint32 idx, i, token;
1959
1960         if (!assembly->save)
1961                 return 0;
1962
1963         sigbuffer_init (&buf, 32);
1964         
1965         sigbuffer_add_value (&buf, 0x06);
1966         /* encode custom attributes before the type */
1967         if (type->num_mods) {
1968                 for (i = 0; i < type->num_mods; ++i) {
1969                         if (field_image) {
1970                                 MonoError error;
1971                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
1972                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1973
1974                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1975                         } else {
1976                                 token = type->modifiers [i].token;
1977                         }
1978
1979                         if (type->modifiers [i].required)
1980                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1981                         else
1982                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1983
1984                         sigbuffer_add_value (&buf, token);
1985                 }
1986         }
1987         encode_type (assembly, type, &buf);
1988         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1989         sigbuffer_free (&buf);
1990         return idx;
1991 }
1992 #endif
1993
1994 static guint32
1995 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1996 {
1997         MONO_REQ_GC_UNSAFE_MODE;
1998
1999         SigBuffer buf;
2000         guint32 idx;
2001         guint32 typespec = 0;
2002         MonoType *type;
2003         MonoClass *klass;
2004
2005         init_type_builder_generics (fb->type);
2006
2007         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
2008         klass = mono_class_from_mono_type (type);
2009
2010         sigbuffer_init (&buf, 32);
2011         
2012         sigbuffer_add_value (&buf, 0x06);
2013         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf);
2014         /* encode custom attributes before the type */
2015
2016         if (klass->generic_container)
2017                 typespec = create_typespec (assembly, type);
2018
2019         if (typespec) {
2020                 MonoGenericClass *gclass;
2021                 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
2022                 encode_generic_class (assembly, gclass, &buf);
2023         } else {
2024                 encode_type (assembly, type, &buf);
2025         }
2026         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2027         sigbuffer_free (&buf);
2028         return idx;
2029 }
2030
2031 static guint32
2032 encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
2033 {
2034         MONO_REQ_GC_UNSAFE_MODE;
2035
2036         char blob_size [64];
2037         char *b = blob_size;
2038         char *box_val;
2039         char* buf;
2040         guint32 idx = 0, len = 0, dummy = 0;
2041
2042         buf = (char *)g_malloc (64);
2043         if (!val) {
2044                 *ret_type = MONO_TYPE_CLASS;
2045                 len = 4;
2046                 box_val = (char*)&dummy;
2047         } else {
2048                 box_val = ((char*)val) + sizeof (MonoObject);
2049                 *ret_type = val->vtable->klass->byval_arg.type;
2050         }
2051 handle_enum:
2052         switch (*ret_type) {
2053         case MONO_TYPE_BOOLEAN:
2054         case MONO_TYPE_U1:
2055         case MONO_TYPE_I1:
2056                 len = 1;
2057                 break;
2058         case MONO_TYPE_CHAR:
2059         case MONO_TYPE_U2:
2060         case MONO_TYPE_I2:
2061                 len = 2;
2062                 break;
2063         case MONO_TYPE_U4:
2064         case MONO_TYPE_I4:
2065         case MONO_TYPE_R4:
2066                 len = 4;
2067                 break;
2068         case MONO_TYPE_U8:
2069         case MONO_TYPE_I8:
2070                 len = 8;
2071                 break;
2072         case MONO_TYPE_R8:
2073                 len = 8;
2074                 break;
2075         case MONO_TYPE_VALUETYPE: {
2076                 MonoClass *klass = val->vtable->klass;
2077                 
2078                 if (klass->enumtype) {
2079                         *ret_type = mono_class_enum_basetype (klass)->type;
2080                         goto handle_enum;
2081                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
2082                         len = 8;
2083                 } else 
2084                         g_error ("we can't encode valuetypes, we should have never reached this line");
2085                 break;
2086         }
2087         case MONO_TYPE_CLASS:
2088                 break;
2089         case MONO_TYPE_STRING: {
2090                 MonoString *str = (MonoString*)val;
2091                 /* there is no signature */
2092                 len = str->length * 2;
2093                 mono_metadata_encode_value (len, b, &b);
2094 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2095                 {
2096                         char *swapped = g_malloc (2 * mono_string_length (str));
2097                         const char *p = (const char*)mono_string_chars (str);
2098
2099                         swap_with_size (swapped, p, 2, mono_string_length (str));
2100                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
2101                         g_free (swapped);
2102                 }
2103 #else
2104                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
2105 #endif
2106
2107                 g_free (buf);
2108                 return idx;
2109         }
2110         case MONO_TYPE_GENERICINST:
2111                 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
2112                 goto handle_enum;
2113         default:
2114                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
2115         }
2116
2117         /* there is no signature */
2118         mono_metadata_encode_value (len, b, &b);
2119 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
2120         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2121         swap_with_size (blob_size, box_val, len, 1);
2122         mono_image_add_stream_data (&assembly->blob, blob_size, len);
2123 #else
2124         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
2125 #endif
2126
2127         g_free (buf);
2128         return idx;
2129 }
2130
2131 static guint32
2132 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo)
2133 {
2134         MONO_REQ_GC_UNSAFE_MODE;
2135
2136         char *str;
2137         SigBuffer buf;
2138         guint32 idx, len;
2139
2140         sigbuffer_init (&buf, 32);
2141
2142         sigbuffer_add_value (&buf, minfo->type);
2143
2144         switch (minfo->type) {
2145         case MONO_NATIVE_BYVALTSTR:
2146         case MONO_NATIVE_BYVALARRAY:
2147                 sigbuffer_add_value (&buf, minfo->count);
2148                 break;
2149         case MONO_NATIVE_LPARRAY:
2150                 if (minfo->eltype || minfo->has_size) {
2151                         sigbuffer_add_value (&buf, minfo->eltype);
2152                         if (minfo->has_size) {
2153                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
2154                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
2155
2156                                 /* LAMESPEC: ElemMult is undocumented */
2157                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
2158                         }
2159                 }
2160                 break;
2161         case MONO_NATIVE_SAFEARRAY:
2162                 if (minfo->eltype)
2163                         sigbuffer_add_value (&buf, minfo->eltype);
2164                 break;
2165         case MONO_NATIVE_CUSTOM:
2166                 if (minfo->guid) {
2167                         str = mono_string_to_utf8 (minfo->guid);
2168                         len = strlen (str);
2169                         sigbuffer_add_value (&buf, len);
2170                         sigbuffer_add_mem (&buf, str, len);
2171                         g_free (str);
2172                 } else {
2173                         sigbuffer_add_value (&buf, 0);
2174                 }
2175                 /* native type name */
2176                 sigbuffer_add_value (&buf, 0);
2177                 /* custom marshaler type name */
2178                 if (minfo->marshaltype || minfo->marshaltyperef) {
2179                         if (minfo->marshaltyperef)
2180                                 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
2181                         else
2182                                 str = mono_string_to_utf8 (minfo->marshaltype);
2183                         len = strlen (str);
2184                         sigbuffer_add_value (&buf, len);
2185                         sigbuffer_add_mem (&buf, str, len);
2186                         g_free (str);
2187                 } else {
2188                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
2189                         sigbuffer_add_value (&buf, 0);
2190                 }
2191                 if (minfo->mcookie) {
2192                         str = mono_string_to_utf8 (minfo->mcookie);
2193                         len = strlen (str);
2194                         sigbuffer_add_value (&buf, len);
2195                         sigbuffer_add_mem (&buf, str, len);
2196                         g_free (str);
2197                 } else {
2198                         sigbuffer_add_value (&buf, 0);
2199                 }
2200                 break;
2201         default:
2202                 break;
2203         }
2204         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2205         sigbuffer_free (&buf);
2206         return idx;
2207 }
2208
2209 static void
2210 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
2211 {
2212         MONO_REQ_GC_UNSAFE_MODE;
2213
2214         MonoDynamicTable *table;
2215         guint32 *values;
2216
2217         /* maybe this fixup should be done in the C# code */
2218         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
2219                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
2220         table = &assembly->tables [MONO_TABLE_FIELD];
2221         fb->table_idx = table->next_idx ++;
2222         g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
2223         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
2224         values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
2225         values [MONO_FIELD_FLAGS] = fb->attrs;
2226         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
2227
2228         if (fb->offset != -1) {
2229                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
2230                 table->rows ++;
2231                 alloc_table (table, table->rows);
2232                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
2233                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
2234                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
2235         }
2236         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
2237                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2238                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2239                 table->rows ++;
2240                 alloc_table (table, table->rows);
2241                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2242                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
2243                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
2244                 values [MONO_CONSTANT_TYPE] = field_type;
2245                 values [MONO_CONSTANT_PADDING] = 0;
2246         }
2247         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
2248                 guint32 rva_idx;
2249                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
2250                 table->rows ++;
2251                 alloc_table (table, table->rows);
2252                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
2253                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
2254                 /*
2255                  * We store it in the code section because it's simpler for now.
2256                  */
2257                 if (fb->rva_data) {
2258                         if (mono_array_length (fb->rva_data) >= 10)
2259                                 stream_data_align (&assembly->code);
2260                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
2261                 } else
2262                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
2263                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
2264         }
2265         if (fb->marshal_info) {
2266                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
2267                 table->rows ++;
2268                 alloc_table (table, table->rows);
2269                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
2270                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
2271                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
2272         }
2273 }
2274
2275 static guint32
2276 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
2277 {
2278         MONO_REQ_GC_UNSAFE_MODE;
2279
2280         SigBuffer buf;
2281         guint32 nparams = 0;
2282         MonoReflectionMethodBuilder *mb = fb->get_method;
2283         MonoReflectionMethodBuilder *smb = fb->set_method;
2284         guint32 idx, i;
2285
2286         if (mb && mb->parameters)
2287                 nparams = mono_array_length (mb->parameters);
2288         if (!mb && smb && smb->parameters)
2289                 nparams = mono_array_length (smb->parameters) - 1;
2290         sigbuffer_init (&buf, 32);
2291         if (fb->call_conv & 0x20)
2292                 sigbuffer_add_byte (&buf, 0x28);
2293         else
2294                 sigbuffer_add_byte (&buf, 0x08);
2295         sigbuffer_add_value (&buf, nparams);
2296         if (mb) {
2297                 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
2298                 for (i = 0; i < nparams; ++i) {
2299                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
2300                         encode_reflection_type (assembly, pt, &buf);
2301                 }
2302         } else if (smb && smb->parameters) {
2303                 /* the property type is the last param */
2304                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
2305                 for (i = 0; i < nparams; ++i) {
2306                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
2307                         encode_reflection_type (assembly, pt, &buf);
2308                 }
2309         } else {
2310                 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2311         }
2312
2313         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2314         sigbuffer_free (&buf);
2315         return idx;
2316 }
2317
2318 static void
2319 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2320 {
2321         MONO_REQ_GC_UNSAFE_MODE;
2322
2323         MonoDynamicTable *table;
2324         guint32 *values;
2325         guint num_methods = 0;
2326         guint32 semaidx;
2327
2328         /* 
2329          * we need to set things in the following tables:
2330          * PROPERTYMAP (info already filled in _get_type_info ())
2331          * PROPERTY    (rows already preallocated in _get_type_info ())
2332          * METHOD      (method info already done with the generic method code)
2333          * METHODSEMANTICS
2334          * CONSTANT
2335          */
2336         table = &assembly->tables [MONO_TABLE_PROPERTY];
2337         pb->table_idx = table->next_idx ++;
2338         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2339         values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2340         values [MONO_PROPERTY_FLAGS] = pb->attrs;
2341         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2342
2343         /* FIXME: we still don't handle 'other' methods */
2344         if (pb->get_method) num_methods ++;
2345         if (pb->set_method) num_methods ++;
2346
2347         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2348         table->rows += num_methods;
2349         alloc_table (table, table->rows);
2350
2351         if (pb->get_method) {
2352                 semaidx = table->next_idx ++;
2353                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2354                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2355                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2356                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2357         }
2358         if (pb->set_method) {
2359                 semaidx = table->next_idx ++;
2360                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2361                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2362                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2363                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2364         }
2365         if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2366                 MonoTypeEnum field_type = (MonoTypeEnum)0;
2367                 table = &assembly->tables [MONO_TABLE_CONSTANT];
2368                 table->rows ++;
2369                 alloc_table (table, table->rows);
2370                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2371                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2372                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2373                 values [MONO_CONSTANT_TYPE] = field_type;
2374                 values [MONO_CONSTANT_PADDING] = 0;
2375         }
2376 }
2377
2378 static void
2379 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2380 {
2381         MONO_REQ_GC_UNSAFE_MODE;
2382
2383         MonoDynamicTable *table;
2384         guint32 *values;
2385         guint num_methods = 0;
2386         guint32 semaidx;
2387
2388         /* 
2389          * we need to set things in the following tables:
2390          * EVENTMAP (info already filled in _get_type_info ())
2391          * EVENT    (rows already preallocated in _get_type_info ())
2392          * METHOD      (method info already done with the generic method code)
2393          * METHODSEMANTICS
2394          */
2395         table = &assembly->tables [MONO_TABLE_EVENT];
2396         eb->table_idx = table->next_idx ++;
2397         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2398         values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2399         values [MONO_EVENT_FLAGS] = eb->attrs;
2400         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2401
2402         /*
2403          * FIXME: we still don't handle 'other' methods 
2404          */
2405         if (eb->add_method) num_methods ++;
2406         if (eb->remove_method) num_methods ++;
2407         if (eb->raise_method) num_methods ++;
2408
2409         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2410         table->rows += num_methods;
2411         alloc_table (table, table->rows);
2412
2413         if (eb->add_method) {
2414                 semaidx = table->next_idx ++;
2415                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2416                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2417                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2418                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2419         }
2420         if (eb->remove_method) {
2421                 semaidx = table->next_idx ++;
2422                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2423                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2424                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2425                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2426         }
2427         if (eb->raise_method) {
2428                 semaidx = table->next_idx ++;
2429                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2430                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2431                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2432                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2433         }
2434 }
2435
2436 static void
2437 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2438 {
2439         MONO_REQ_GC_UNSAFE_MODE;
2440
2441         MonoDynamicTable *table;
2442         guint32 num_constraints, i;
2443         guint32 *values;
2444         guint32 table_idx;
2445
2446         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2447         num_constraints = gparam->iface_constraints ?
2448                 mono_array_length (gparam->iface_constraints) : 0;
2449         table->rows += num_constraints;
2450         if (gparam->base_type)
2451                 table->rows++;
2452         alloc_table (table, table->rows);
2453
2454         if (gparam->base_type) {
2455                 table_idx = table->next_idx ++;
2456                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2457
2458                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2459                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2460                         assembly, mono_reflection_type_get_handle (gparam->base_type));
2461         }
2462
2463         for (i = 0; i < num_constraints; i++) {
2464                 MonoReflectionType *constraint = (MonoReflectionType *)mono_array_get (
2465                         gparam->iface_constraints, gpointer, i);
2466
2467                 table_idx = table->next_idx ++;
2468                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2469
2470                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2471                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2472                         assembly, mono_reflection_type_get_handle (constraint));
2473         }
2474 }
2475
2476 static void
2477 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2478 {
2479         MONO_REQ_GC_UNSAFE_MODE;
2480
2481         GenericParamTableEntry *entry;
2482
2483         /*
2484          * The GenericParam table must be sorted according to the `owner' field.
2485          * We need to do this sorting prior to writing the GenericParamConstraint
2486          * table, since we have to use the final GenericParam table indices there
2487          * and they must also be sorted.
2488          */
2489
2490         entry = g_new0 (GenericParamTableEntry, 1);
2491         entry->owner = owner;
2492         /* FIXME: track where gen_params should be freed and remove the GC root as well */
2493         MONO_GC_REGISTER_ROOT_IF_MOVING (entry->gparam, MONO_ROOT_SOURCE_REFLECTION, "reflection generic parameter");
2494         entry->gparam = gparam;
2495         
2496         g_ptr_array_add (assembly->gen_params, entry);
2497 }
2498
2499 static gboolean
2500 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry, MonoError *error)
2501 {
2502         MONO_REQ_GC_UNSAFE_MODE;
2503
2504         MonoDynamicTable *table;
2505         MonoGenericParam *param;
2506         guint32 *values;
2507         guint32 table_idx;
2508
2509         mono_error_init (error);
2510
2511         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2512         table_idx = table->next_idx ++;
2513         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2514
2515         param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2516
2517         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2518         values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2519         values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2520         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2521
2522         if (!mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs, error))
2523                 return FALSE;
2524
2525         encode_constraints (entry->gparam, table_idx, assembly);
2526
2527         return TRUE;
2528 }
2529
2530 static guint32
2531 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2532 {
2533         MONO_REQ_GC_UNSAFE_MODE;
2534
2535         MonoDynamicTable *table;
2536         guint32 token;
2537         guint32 *values;
2538         guint32 cols [MONO_ASSEMBLY_SIZE];
2539         const char *pubkey;
2540         guint32 publen;
2541
2542         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2543                 return token;
2544
2545         if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
2546                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2547                 token = table->next_idx ++;
2548                 table->rows ++;
2549                 alloc_table (table, table->rows);
2550                 values = table->values + token * MONO_MODULEREF_SIZE;
2551                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2552
2553                 token <<= MONO_RESOLUTION_SCOPE_BITS;
2554                 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
2555                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2556
2557                 return token;
2558         }
2559         
2560         if (assembly_is_dynamic (image->assembly))
2561                 /* FIXME: */
2562                 memset (cols, 0, sizeof (cols));
2563         else {
2564                 /* image->assembly->image is the manifest module */
2565                 image = image->assembly->image;
2566                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2567         }
2568
2569         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2570         token = table->next_idx ++;
2571         table->rows ++;
2572         alloc_table (table, table->rows);
2573         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2574         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2575         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2576         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2577         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2578         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2579         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2580         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2581         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2582
2583         if (strcmp ("", image->assembly->aname.culture)) {
2584                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2585                                 image->assembly->aname.culture);
2586         }
2587
2588         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2589                 guchar pubtoken [9];
2590                 pubtoken [0] = 8;
2591                 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2592                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2593         } else {
2594                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2595         }
2596         token <<= MONO_RESOLUTION_SCOPE_BITS;
2597         token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
2598         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2599         return token;
2600 }
2601
2602 static guint32
2603 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2604 {
2605         MONO_REQ_GC_NEUTRAL_MODE;
2606
2607         MonoDynamicTable *table;
2608         guint32 *values;
2609         guint32 token;
2610         SigBuffer buf;
2611
2612         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2613                 return token;
2614
2615         sigbuffer_init (&buf, 32);
2616         switch (type->type) {
2617         case MONO_TYPE_FNPTR:
2618         case MONO_TYPE_PTR:
2619         case MONO_TYPE_SZARRAY:
2620         case MONO_TYPE_ARRAY:
2621         case MONO_TYPE_VAR:
2622         case MONO_TYPE_MVAR:
2623         case MONO_TYPE_GENERICINST:
2624                 encode_type (assembly, type, &buf);
2625                 break;
2626         case MONO_TYPE_CLASS:
2627         case MONO_TYPE_VALUETYPE: {
2628                 MonoClass *k = mono_class_from_mono_type (type);
2629                 if (!k || !k->generic_container) {
2630                         sigbuffer_free (&buf);
2631                         return 0;
2632                 }
2633                 encode_type (assembly, type, &buf);
2634                 break;
2635         }
2636         default:
2637                 sigbuffer_free (&buf);
2638                 return 0;
2639         }
2640
2641         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2642         if (assembly->save) {
2643                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2644                 alloc_table (table, table->rows + 1);
2645                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2646                 values [MONO_TYPESPEC_SIGNATURE] = token;
2647         }
2648         sigbuffer_free (&buf);
2649
2650         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2651         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2652         table->next_idx ++;
2653         return token;
2654 }
2655
2656 static guint32
2657 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2658 {
2659         MONO_REQ_GC_UNSAFE_MODE;
2660
2661         MonoDynamicTable *table;
2662         guint32 *values;
2663         guint32 token, scope, enclosing;
2664         MonoClass *klass;
2665
2666         /* if the type requires a typespec, we must try that first*/
2667         if (try_typespec && (token = create_typespec (assembly, type)))
2668                 return token;
2669         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2670         if (token)
2671                 return token;
2672         klass = mono_class_from_mono_type (type);
2673         if (!klass)
2674                 klass = mono_class_from_mono_type (type);
2675
2676         /*
2677          * If it's in the same module and not a generic type parameter:
2678          */
2679         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2680                         (type->type != MONO_TYPE_MVAR)) {
2681                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
2682                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2683                 register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2684                 return token;
2685         }
2686
2687         if (klass->nested_in) {
2688                 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2689                 /* get the typeref idx of the enclosing type */
2690                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2691                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
2692         } else {
2693                 scope = resolution_scope_from_image (assembly, klass->image);
2694         }
2695         table = &assembly->tables [MONO_TABLE_TYPEREF];
2696         if (assembly->save) {
2697                 alloc_table (table, table->rows + 1);
2698                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2699                 values [MONO_TYPEREF_SCOPE] = scope;
2700                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2701                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2702         }
2703         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2704         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2705         table->next_idx ++;
2706         register_dyn_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
2707         return token;
2708 }
2709
2710 /*
2711  * Despite the name, we handle also TypeSpec (with the above helper).
2712  */
2713 static guint32
2714 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2715 {
2716         return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2717 }
2718
2719 #ifndef DISABLE_REFLECTION_EMIT
2720 static guint32
2721 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2722 {
2723         MONO_REQ_GC_NEUTRAL_MODE;
2724
2725         MonoDynamicTable *table;
2726         guint32 *values;
2727         guint32 token, pclass;
2728
2729         switch (parent & MONO_TYPEDEFORREF_MASK) {
2730         case MONO_TYPEDEFORREF_TYPEREF:
2731                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2732                 break;
2733         case MONO_TYPEDEFORREF_TYPESPEC:
2734                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2735                 break;
2736         case MONO_TYPEDEFORREF_TYPEDEF:
2737                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2738                 break;
2739         default:
2740                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2741                 return 0;
2742         }
2743         /* extract the index */
2744         parent >>= MONO_TYPEDEFORREF_BITS;
2745
2746         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2747
2748         if (assembly->save) {
2749                 alloc_table (table, table->rows + 1);
2750                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2751                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2752                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2753                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2754         }
2755
2756         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2757         table->next_idx ++;
2758
2759         return token;
2760 }
2761
2762 /*
2763  * Insert a memberef row into the metadata: the token that point to the memberref
2764  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2765  * mono_image_get_fieldref_token()).
2766  * The sig param is an index to an already built signature.
2767  */
2768 static guint32
2769 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2770 {
2771         MONO_REQ_GC_NEUTRAL_MODE;
2772
2773         guint32 parent = mono_image_typedef_or_ref (assembly, type);
2774         return mono_image_add_memberef_row (assembly, parent, name, sig);
2775 }
2776
2777
2778 static guint32
2779 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2780 {
2781         MONO_REQ_GC_NEUTRAL_MODE;
2782
2783         guint32 token;
2784         MonoMethodSignature *sig;
2785         
2786         create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2787
2788         if (create_typespec) {
2789                 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2790                 if (token)
2791                         return token;
2792         } 
2793
2794         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2795         if (token && !create_typespec)
2796                 return token;
2797
2798         g_assert (!method->is_inflated);
2799         if (!token) {
2800                 /*
2801                  * A methodref signature can't contain an unmanaged calling convention.
2802                  */
2803                 sig = mono_metadata_signature_dup (mono_method_signature (method));
2804                 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2805                         sig->call_convention = MONO_CALL_DEFAULT;
2806                 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2807                         method->name,  method_encode_signature (assembly, sig));
2808                 g_free (sig);
2809                 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2810         }
2811
2812         if (create_typespec) {
2813                 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2814                 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2815                 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2816
2817                 if (assembly->save) {
2818                         guint32 *values;
2819
2820                         alloc_table (table, table->rows + 1);
2821                         values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2822                         values [MONO_METHODSPEC_METHOD] = token;
2823                         values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2824                 }
2825
2826                 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2827                 table->next_idx ++;
2828                 /*methodspec and memberef tokens are diferent, */
2829                 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2830                 return token;
2831         }
2832         return token;
2833 }
2834
2835 static guint32
2836 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method, MonoError *error)
2837 {
2838         guint32 token, parent, sig;
2839         ReflectionMethodBuilder rmb;
2840         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2841         
2842         mono_error_init (error);
2843         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2844         if (token)
2845                 return token;
2846
2847         if (!reflection_methodbuilder_from_method_builder (&rmb, method, error))
2848                 return 0;
2849
2850         /*
2851          * A methodref signature can't contain an unmanaged calling convention.
2852          * Since some flags are encoded as part of call_conv, we need to check against it.
2853         */
2854         if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2855                 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2856
2857         sig = method_builder_encode_signature (assembly, &rmb);
2858
2859         if (tb->generic_params)
2860                 parent = create_generic_typespec (assembly, tb);
2861         else
2862                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2863
2864         char *name = mono_string_to_utf8 (method->name);
2865
2866         token = mono_image_add_memberef_row (assembly, parent, name, sig);
2867         g_free (name);
2868
2869         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2870
2871         return token;
2872 }
2873
2874 static guint32
2875 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2876                                      const gchar *name, guint32 sig)
2877 {
2878         MonoDynamicTable *table;
2879         guint32 token;
2880         guint32 *values;
2881         
2882         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2883
2884         if (assembly->save) {
2885                 alloc_table (table, table->rows + 1);
2886                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2887                 values [MONO_MEMBERREF_CLASS] = original;
2888                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2889                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2890         }
2891
2892         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2893         table->next_idx ++;
2894
2895         return token;
2896 }
2897
2898 static guint32
2899 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2900 {
2901         SigBuffer buf;
2902         int i;
2903         guint32 nparams = mono_array_length (mb->generic_params);
2904         guint32 idx;
2905
2906         if (!assembly->save)
2907                 return 0;
2908
2909         sigbuffer_init (&buf, 32);
2910
2911         sigbuffer_add_value (&buf, 0xa);
2912         sigbuffer_add_value (&buf, nparams);
2913
2914         for (i = 0; i < nparams; i++) {
2915                 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2916                 sigbuffer_add_value (&buf, i);
2917         }
2918
2919         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2920         sigbuffer_free (&buf);
2921         return idx;
2922 }
2923
2924 static guint32
2925 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, MonoError *error)
2926 {
2927         MonoDynamicTable *table;
2928         guint32 *values;
2929         guint32 token, mtoken = 0;
2930
2931         mono_error_init (error);
2932         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2933         if (token)
2934                 return token;
2935
2936         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2937
2938         mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2939         if (!mono_error_ok (error))
2940                 return 0;
2941
2942         switch (mono_metadata_token_table (mtoken)) {
2943         case MONO_TABLE_MEMBERREF:
2944                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2945                 break;
2946         case MONO_TABLE_METHOD:
2947                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2948                 break;
2949         default:
2950                 g_assert_not_reached ();
2951         }
2952
2953         if (assembly->save) {
2954                 alloc_table (table, table->rows + 1);
2955                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2956                 values [MONO_METHODSPEC_METHOD] = mtoken;
2957                 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2958         }
2959
2960         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2961         table->next_idx ++;
2962
2963         mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2964         return token;
2965 }
2966
2967 static guint32
2968 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec, MonoError *error)
2969 {
2970         guint32 token;
2971
2972         mono_error_init (error);
2973
2974         if (mb->generic_params && create_methodspec) 
2975                 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb, error);
2976
2977         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2978         if (token)
2979                 return token;
2980
2981         token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb, error);
2982         if (!mono_error_ok (error))
2983                 return 0;
2984         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2985         return token;
2986 }
2987
2988 static guint32
2989 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb, MonoError *error)
2990 {
2991         guint32 token, parent, sig;
2992         ReflectionMethodBuilder rmb;
2993         char *name;
2994         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2995         
2996         mono_error_init (error);
2997         
2998         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2999         if (token)
3000                 return token;
3001
3002         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3003                 return 0;
3004
3005         if (tb->generic_params)
3006                 parent = create_generic_typespec (assembly, tb);
3007         else
3008                 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3009         
3010         name = mono_string_to_utf8 (rmb.name);
3011         sig = method_builder_encode_signature (assembly, &rmb);
3012
3013         token = mono_image_add_memberef_row (assembly, parent, name, sig);
3014
3015         g_free (name);
3016         mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
3017         return token;
3018 }
3019 #endif
3020
3021 static gboolean
3022 is_field_on_inst (MonoClassField *field)
3023 {
3024         return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
3025 }
3026
3027 /*
3028  * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
3029  */
3030 static MonoType*
3031 get_field_on_inst_generic_type (MonoClassField *field)
3032 {
3033         MonoClass *klass, *gtd;
3034         MonoDynamicGenericClass *dgclass;
3035         int field_index;
3036
3037         g_assert (is_field_on_inst (field));
3038
3039         dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
3040
3041         if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
3042                 field_index = field - dgclass->fields;
3043                 return dgclass->field_generic_types [field_index];              
3044         }
3045
3046         klass = field->parent;
3047         gtd = klass->generic_class->container_class;
3048
3049         if (field >= klass->fields && field - klass->fields < klass->field.count) {
3050                 field_index = field - klass->fields;
3051                 return gtd->fields [field_index].type;
3052         }
3053
3054         g_assert_not_reached ();
3055         return 0;
3056 }
3057
3058 #ifndef DISABLE_REFLECTION_EMIT
3059 static guint32
3060 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
3061 {
3062         MonoType *type;
3063         guint32 token;
3064
3065         g_assert (field);
3066         g_assert (field->parent);
3067
3068         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3069         if (token)
3070                 return token;
3071
3072         if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
3073                 int index = field - field->parent->fields;
3074                 type = mono_field_get_type (&field->parent->generic_class->container_class->fields [index]);
3075         } else {
3076                 if (is_field_on_inst (field))
3077                         type = get_field_on_inst_generic_type (field);
3078                 else
3079                         type = mono_field_get_type (field);
3080         }
3081         token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
3082                                                                                         mono_field_get_name (field),
3083                                                                                         fieldref_encode_signature (assembly, field->parent->image, type));
3084         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
3085         return token;
3086 }
3087
3088 static guint32
3089 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
3090 {
3091         guint32 token;
3092         MonoClass *klass;
3093         MonoGenericClass *gclass;
3094         MonoType *type;
3095         char *name;
3096
3097         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
3098         if (token)
3099                 return token;
3100         if (is_sre_field_builder (mono_object_class (f->fb))) {
3101                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
3102                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3103                 klass = mono_class_from_mono_type (type);
3104                 gclass = type->data.generic_class;
3105                 g_assert (gclass->is_dynamic);
3106
3107                 name = mono_string_to_utf8 (fb->name);
3108                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, 
3109                                                                                                 field_encode_signature (assembly, fb));
3110                 g_free (name);          
3111         } else if (is_sr_mono_field (mono_object_class (f->fb))) {
3112                 guint32 sig;
3113                 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
3114
3115                 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
3116                 klass = mono_class_from_mono_type (type);
3117
3118                 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
3119                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
3120         } else {
3121                 char *name = mono_type_get_full_name (mono_object_class (f->fb));
3122                 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
3123         }
3124
3125         mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
3126         return token;
3127 }
3128
3129 static guint32
3130 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec, MonoError *error)
3131 {
3132         guint32 sig, token;
3133         MonoClass *klass;
3134         MonoGenericClass *gclass;
3135         MonoType *type;
3136
3137         mono_error_init (error);
3138
3139         /* A ctor cannot be a generic method, so we can ignore create_methodspec */
3140
3141         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
3142         if (token)
3143                 return token;
3144
3145         if (is_sre_ctor_builder (mono_object_class (c->cb))) {
3146                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
3147                 ReflectionMethodBuilder rmb;
3148                 char *name;
3149
3150                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3151                 klass = mono_class_from_mono_type (type);
3152
3153                 gclass = type->data.generic_class;
3154                 g_assert (gclass->is_dynamic);
3155
3156                 if (!reflection_methodbuilder_from_ctor_builder (&rmb, cb, error))
3157                         return 0;
3158
3159                 name = mono_string_to_utf8 (rmb.name);
3160
3161                 sig = method_builder_encode_signature (assembly, &rmb);
3162
3163                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3164                 g_free (name);
3165         } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
3166                 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
3167
3168                 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
3169                 klass = mono_class_from_mono_type (type);
3170
3171                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3172                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3173         } else {
3174                 char *name = mono_type_get_full_name (mono_object_class (c->cb));
3175                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3176         }
3177
3178
3179         mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
3180         return token;
3181 }
3182
3183 static MonoMethod*
3184 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m, MonoError *error)
3185 {
3186         MonoClass *klass;
3187         MonoGenericContext tmp_context;
3188         MonoType **type_argv;
3189         MonoGenericInst *ginst;
3190         MonoMethod *method, *inflated;
3191         int count, i;
3192
3193         mono_error_init (error);
3194
3195         init_type_builder_generics ((MonoObject*)m->inst);
3196
3197         method = inflate_method (m->inst, (MonoObject*)m->mb, error);
3198         return_val_if_nok (error, NULL);
3199
3200         klass = method->klass;
3201
3202         if (m->method_args == NULL)
3203                 return method;
3204
3205         if (method->is_inflated)
3206                 method = ((MonoMethodInflated *) method)->declaring;
3207
3208         count = mono_array_length (m->method_args);
3209
3210         type_argv = g_new0 (MonoType *, count);
3211         for (i = 0; i < count; i++) {
3212                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (m->method_args, gpointer, i);
3213                 type_argv [i] = mono_reflection_type_get_handle (garg);
3214         }
3215         ginst = mono_metadata_get_generic_inst (count, type_argv);
3216         g_free (type_argv);
3217
3218         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
3219         tmp_context.method_inst = ginst;
3220
3221         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
3222         mono_error_assert_ok (error);
3223         return inflated;
3224 }
3225
3226 static guint32
3227 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec, MonoError *error)
3228 {
3229         guint32 sig, token = 0;
3230         MonoType *type;
3231         MonoClass *klass;
3232
3233         mono_error_init (error);
3234
3235         if (m->method_args) {
3236                 MonoMethod *inflated;
3237
3238                 inflated = mono_reflection_method_on_tb_inst_get_handle (m, error);
3239                 return_val_if_nok (error, 0);
3240
3241                 if (create_methodspec)
3242                         token = mono_image_get_methodspec_token (assembly, inflated);
3243                 else
3244                         token = mono_image_get_inflated_method_token (assembly, inflated);
3245                 return token;
3246         }
3247
3248         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
3249         if (token)
3250                 return token;
3251
3252         if (is_sre_method_builder (mono_object_class (m->mb))) {
3253                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
3254                 MonoGenericClass *gclass;
3255                 ReflectionMethodBuilder rmb;
3256                 char *name;
3257
3258                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3259                 klass = mono_class_from_mono_type (type);
3260                 gclass = type->data.generic_class;
3261                 g_assert (gclass->is_dynamic);
3262
3263                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3264                         return 0;
3265
3266                 name = mono_string_to_utf8 (rmb.name);
3267
3268                 sig = method_builder_encode_signature (assembly, &rmb);
3269
3270                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
3271                 g_free (name);          
3272         } else if (is_sr_mono_method (mono_object_class (m->mb))) {
3273                 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
3274
3275                 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
3276                 klass = mono_class_from_mono_type (type);
3277
3278                 sig = method_encode_signature (assembly, mono_method_signature (mm));
3279                 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
3280         } else {
3281                 char *name = mono_type_get_full_name (mono_object_class (m->mb));
3282                 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
3283         }
3284
3285         mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
3286         return token;
3287 }
3288
3289 static guint32
3290 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
3291 {
3292         SigBuffer buf;
3293         int i;
3294         guint32 nparams = context->method_inst->type_argc;
3295         guint32 idx;
3296
3297         if (!assembly->save)
3298                 return 0;
3299
3300         sigbuffer_init (&buf, 32);
3301         /*
3302          * FIXME: vararg, explicit_this, differenc call_conv values...
3303          */
3304         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
3305         sigbuffer_add_value (&buf, nparams);
3306
3307         for (i = 0; i < nparams; i++)
3308                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
3309
3310         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3311         sigbuffer_free (&buf);
3312         return idx;
3313 }
3314
3315 static guint32
3316 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
3317 {
3318         MonoDynamicTable *table;
3319         guint32 *values;
3320         guint32 token, mtoken = 0, sig;
3321         MonoMethodInflated *imethod;
3322         MonoMethod *declaring;
3323
3324         table = &assembly->tables [MONO_TABLE_METHODSPEC];
3325
3326         g_assert (method->is_inflated);
3327         imethod = (MonoMethodInflated *) method;
3328         declaring = imethod->declaring;
3329
3330         sig = method_encode_signature (assembly, mono_method_signature (declaring));
3331         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
3332
3333         if (!mono_method_signature (declaring)->generic_param_count)
3334                 return mtoken;
3335
3336         switch (mono_metadata_token_table (mtoken)) {
3337         case MONO_TABLE_MEMBERREF:
3338                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3339                 break;
3340         case MONO_TABLE_METHOD:
3341                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3342                 break;
3343         default:
3344                 g_assert_not_reached ();
3345         }
3346
3347         sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3348
3349         if (assembly->save) {
3350                 alloc_table (table, table->rows + 1);
3351                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3352                 values [MONO_METHODSPEC_METHOD] = mtoken;
3353                 values [MONO_METHODSPEC_SIGNATURE] = sig;
3354         }
3355
3356         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3357         table->next_idx ++;
3358
3359         return token;
3360 }
3361
3362 static guint32
3363 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3364 {
3365         MonoMethodInflated *imethod;
3366         guint32 token;
3367         
3368         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3369         if (token)
3370                 return token;
3371
3372         g_assert (method->is_inflated);
3373         imethod = (MonoMethodInflated *) method;
3374
3375         if (mono_method_signature (imethod->declaring)->generic_param_count) {
3376                 token = method_encode_methodspec (assembly, method);
3377         } else {
3378                 guint32 sig = method_encode_signature (
3379                         assembly, mono_method_signature (imethod->declaring));
3380                 token = mono_image_get_memberref_token (
3381                         assembly, &method->klass->byval_arg, method->name, sig);
3382         }
3383
3384         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3385         return token;
3386 }
3387
3388 static guint32
3389 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3390 {
3391         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3392         guint32 sig, token;
3393
3394         sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3395         token = mono_image_get_memberref_token (
3396                 assembly, &m->klass->byval_arg, m->name, sig);
3397
3398         return token;
3399 }
3400
3401 static guint32
3402 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3403 {
3404         MonoDynamicTable *table;
3405         MonoClass *klass;
3406         MonoType *type;
3407         guint32 *values;
3408         guint32 token;
3409         SigBuffer buf;
3410         int count, i;
3411
3412         /*
3413          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3414          * ie. what we'd normally use as the generic type in a TypeSpec signature.
3415          * Because of this, we must not insert it into the `typeref' hash table.
3416          */
3417         type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3418         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3419         if (token)
3420                 return token;
3421
3422         sigbuffer_init (&buf, 32);
3423
3424         g_assert (tb->generic_params);
3425         klass = mono_class_from_mono_type (type);
3426
3427         if (tb->generic_container)
3428                 mono_reflection_create_generic_class (tb);
3429
3430         sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3431         g_assert (klass->generic_container);
3432         sigbuffer_add_value (&buf, klass->byval_arg.type);
3433         sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3434
3435         count = mono_array_length (tb->generic_params);
3436         sigbuffer_add_value (&buf, count);
3437         for (i = 0; i < count; i++) {
3438                 MonoReflectionGenericParam *gparam;
3439
3440                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3441
3442                 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3443         }
3444
3445         table = &assembly->tables [MONO_TABLE_TYPESPEC];
3446
3447         if (assembly->save) {
3448                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3449                 alloc_table (table, table->rows + 1);
3450                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3451                 values [MONO_TYPESPEC_SIGNATURE] = token;
3452         }
3453         sigbuffer_free (&buf);
3454
3455         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3456         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3457         table->next_idx ++;
3458         return token;
3459 }
3460
3461 /*
3462  * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3463  */
3464 static MonoType*
3465 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3466 {
3467         int i, count, len, pos;
3468         MonoType *t;
3469
3470         count = 0;
3471         if (modreq)
3472                 count += mono_array_length (modreq);
3473         if (modopt)
3474                 count += mono_array_length (modopt);
3475
3476         if (count == 0)
3477                 return mono_metadata_type_dup (NULL, type);
3478
3479         len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3480         t = (MonoType *)g_malloc (len);
3481         memcpy (t, type, MONO_SIZEOF_TYPE);
3482
3483         t->num_mods = count;
3484         pos = 0;
3485         if (modreq) {
3486                 for (i = 0; i < mono_array_length (modreq); ++i) {
3487                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3488                         t->modifiers [pos].required = 1;
3489                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3490                         pos ++;
3491                 }
3492         }
3493         if (modopt) {
3494                 for (i = 0; i < mono_array_length (modopt); ++i) {
3495                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3496                         t->modifiers [pos].required = 0;
3497                         t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3498                         pos ++;
3499                 }
3500         }
3501
3502         return t;
3503 }
3504
3505 static void
3506 init_type_builder_generics (MonoObject *type)
3507 {
3508         MonoReflectionTypeBuilder *tb;
3509
3510         if (!is_sre_type_builder(mono_object_class (type)))
3511                 return;
3512         tb = (MonoReflectionTypeBuilder *)type;
3513
3514         if (tb && tb->generic_container)
3515                 mono_reflection_create_generic_class (tb);
3516 }
3517
3518 static guint32
3519 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3520 {
3521         MonoDynamicTable *table;
3522         MonoType *custom = NULL, *type;
3523         guint32 *values;
3524         guint32 token, pclass, parent, sig;
3525         gchar *name;
3526
3527         token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3528         if (token)
3529                 return token;
3530
3531         /* FIXME: is this call necessary? */
3532         mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3533         name = mono_string_to_utf8 (fb->name);
3534
3535         /*FIXME this is one more layer of ugliness due how types are created.*/
3536         init_type_builder_generics (fb->type);
3537
3538         /* fb->type does not include the custom modifiers */
3539         /* FIXME: We should do this in one place when a fieldbuilder is created */
3540         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3541         if (fb->modreq || fb->modopt)
3542                 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3543
3544         sig = fieldref_encode_signature (assembly, NULL, type);
3545         g_free (custom);
3546
3547         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3548         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3549         
3550         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3551         parent >>= MONO_TYPEDEFORREF_BITS;
3552
3553         table = &assembly->tables [MONO_TABLE_MEMBERREF];
3554
3555         if (assembly->save) {
3556                 alloc_table (table, table->rows + 1);
3557                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3558                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3559                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3560                 values [MONO_MEMBERREF_SIGNATURE] = sig;
3561         }
3562
3563         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3564         table->next_idx ++;
3565         mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3566         g_free (name);
3567         return token;
3568 }
3569
3570 static guint32
3571 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3572 {
3573         SigBuffer buf;
3574         guint32 nargs;
3575         guint32 i, idx;
3576
3577         if (!assembly->save)
3578                 return 0;
3579
3580         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3581         g_assert (helper->type == 2);
3582
3583         if (helper->arguments)
3584                 nargs = mono_array_length (helper->arguments);
3585         else
3586                 nargs = 0;
3587
3588         sigbuffer_init (&buf, 32);
3589
3590         /* Encode calling convention */
3591         /* Change Any to Standard */
3592         if ((helper->call_conv & 0x03) == 0x03)
3593                 helper->call_conv = 0x01;
3594         /* explicit_this implies has_this */
3595         if (helper->call_conv & 0x40)
3596                 helper->call_conv &= 0x20;
3597
3598         if (helper->call_conv == 0) { /* Unmanaged */
3599                 idx = helper->unmanaged_call_conv - 1;
3600         } else {
3601                 /* Managed */
3602                 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3603                 if (helper->call_conv & 0x02) /* varargs */
3604                         idx += 0x05;
3605         }
3606
3607         sigbuffer_add_byte (&buf, idx);
3608         sigbuffer_add_value (&buf, nargs);
3609         encode_reflection_type (assembly, helper->return_type, &buf);
3610         for (i = 0; i < nargs; ++i) {
3611                 MonoArray *modreqs = NULL;
3612                 MonoArray *modopts = NULL;
3613                 MonoReflectionType *pt;
3614
3615                 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3616                         modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3617                 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3618                         modopts = mono_array_get (helper->modopts, MonoArray*, i);
3619
3620                 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3621                 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3622                 encode_reflection_type (assembly, pt, &buf);
3623         }
3624         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3625         sigbuffer_free (&buf);
3626
3627         return idx;
3628 }
3629
3630 static guint32 
3631 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3632 {
3633         guint32 idx;
3634         MonoDynamicTable *table;
3635         guint32 *values;
3636
3637         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3638         idx = table->next_idx ++;
3639         table->rows ++;
3640         alloc_table (table, table->rows);
3641         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3642
3643         values [MONO_STAND_ALONE_SIGNATURE] =
3644                 mono_reflection_encode_sighelper (assembly, helper);
3645
3646         return idx;
3647 }
3648
3649 static int
3650 reflection_cc_to_file (int call_conv) {
3651         switch (call_conv & 0x3) {
3652         case 0:
3653         case 1: return MONO_CALL_DEFAULT;
3654         case 2: return MONO_CALL_VARARG;
3655         default:
3656                 g_assert_not_reached ();
3657         }
3658         return 0;
3659 }
3660 #endif /* !DISABLE_REFLECTION_EMIT */
3661
3662 typedef struct {
3663         MonoType *parent;
3664         MonoMethodSignature *sig;
3665         char *name;
3666         guint32 token;
3667 } ArrayMethod;
3668
3669 #ifndef DISABLE_REFLECTION_EMIT
3670 static guint32
3671 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3672 {
3673         guint32 nparams, i;
3674         GList *tmp;
3675         char *name;
3676         MonoMethodSignature *sig;
3677         ArrayMethod *am;
3678         MonoType *mtype;
3679
3680         name = mono_string_to_utf8 (m->name);
3681         nparams = mono_array_length (m->parameters);
3682         sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3683         sig->hasthis = 1;
3684         sig->sentinelpos = -1;
3685         sig->call_convention = reflection_cc_to_file (m->call_conv);
3686         sig->param_count = nparams;
3687         sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3688         mtype = mono_reflection_type_get_handle (m->parent);
3689         for (i = 0; i < nparams; ++i)
3690                 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3691
3692         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3693                 am = (ArrayMethod *)tmp->data;
3694                 if (strcmp (name, am->name) == 0 && 
3695                                 mono_metadata_type_equal (am->parent, mtype) &&
3696                                 mono_metadata_signature_equal (am->sig, sig)) {
3697                         g_free (name);
3698                         g_free (sig);
3699                         m->table_idx = am->token & 0xffffff;
3700                         return am->token;
3701                 }
3702         }
3703         am = g_new0 (ArrayMethod, 1);
3704         am->name = name;
3705         am->sig = sig;
3706         am->parent = mtype;
3707         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3708                 method_encode_signature (assembly, sig));
3709         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3710         m->table_idx = am->token & 0xffffff;
3711         return am->token;
3712 }
3713
3714 /*
3715  * Insert into the metadata tables all the info about the TypeBuilder tb.
3716  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3717  */
3718 static gboolean
3719 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly, MonoError *error)
3720 {
3721         MonoDynamicTable *table;
3722         guint *values;
3723         int i, is_object = 0, is_system = 0;
3724         char *n;
3725
3726         mono_error_init (error);
3727
3728         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3729         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3730         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3731         n = mono_string_to_utf8 (tb->name);
3732         if (strcmp (n, "Object") == 0)
3733                 is_object++;
3734         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3735         g_free (n);
3736         n = mono_string_to_utf8 (tb->nspace);
3737         if (strcmp (n, "System") == 0)
3738                 is_system++;
3739         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3740         g_free (n);
3741         if (tb->parent && !(is_system && is_object) && 
3742                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3743                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3744         } else {
3745                 values [MONO_TYPEDEF_EXTENDS] = 0;
3746         }
3747         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3748         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3749
3750         /*
3751          * if we have explicitlayout or sequentiallayouts, output data in the
3752          * ClassLayout table.
3753          */
3754         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3755                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
3756                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3757                 table->rows++;
3758                 alloc_table (table, table->rows);
3759                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3760                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3761                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3762                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3763         }
3764
3765         /* handle interfaces */
3766         if (tb->interfaces) {
3767                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3768                 i = table->rows;
3769                 table->rows += mono_array_length (tb->interfaces);
3770                 alloc_table (table, table->rows);
3771                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3772                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3773                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3774                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3775                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3776                         values += MONO_INTERFACEIMPL_SIZE;
3777                 }
3778         }
3779
3780         /* handle fields */
3781         if (tb->fields) {
3782                 table = &assembly->tables [MONO_TABLE_FIELD];
3783                 table->rows += tb->num_fields;
3784                 alloc_table (table, table->rows);
3785                 for (i = 0; i < tb->num_fields; ++i)
3786                         mono_image_get_field_info (
3787                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3788         }
3789
3790         /* handle constructors */
3791         if (tb->ctors) {
3792                 table = &assembly->tables [MONO_TABLE_METHOD];
3793                 table->rows += mono_array_length (tb->ctors);
3794                 alloc_table (table, table->rows);
3795                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3796                         if (!mono_image_get_ctor_info (domain,
3797                                                        mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i),
3798                                                        assembly, error))
3799                                 return FALSE;
3800                 }
3801         }
3802
3803         /* handle methods */
3804         if (tb->methods) {
3805                 table = &assembly->tables [MONO_TABLE_METHOD];
3806                 table->rows += tb->num_methods;
3807                 alloc_table (table, table->rows);
3808                 for (i = 0; i < tb->num_methods; ++i) {
3809                         if (!mono_image_get_method_info (
3810                                     mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly, error))
3811                                 return FALSE;
3812                 }
3813         }
3814
3815         /* Do the same with properties etc.. */
3816         if (tb->events && mono_array_length (tb->events)) {
3817                 table = &assembly->tables [MONO_TABLE_EVENT];
3818                 table->rows += mono_array_length (tb->events);
3819                 alloc_table (table, table->rows);
3820                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3821                 table->rows ++;
3822                 alloc_table (table, table->rows);
3823                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3824                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3825                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3826                 for (i = 0; i < mono_array_length (tb->events); ++i)
3827                         mono_image_get_event_info (
3828                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3829         }
3830         if (tb->properties && mono_array_length (tb->properties)) {
3831                 table = &assembly->tables [MONO_TABLE_PROPERTY];
3832                 table->rows += mono_array_length (tb->properties);
3833                 alloc_table (table, table->rows);
3834                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3835                 table->rows ++;
3836                 alloc_table (table, table->rows);
3837                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3838                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3839                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3840                 for (i = 0; i < mono_array_length (tb->properties); ++i)
3841                         mono_image_get_property_info (
3842                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3843         }
3844
3845         /* handle generic parameters */
3846         if (tb->generic_params) {
3847                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3848                 table->rows += mono_array_length (tb->generic_params);
3849                 alloc_table (table, table->rows);
3850                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3851                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3852
3853                         mono_image_get_generic_param_info (
3854                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3855                 }
3856         }
3857
3858         mono_image_add_decl_security (assembly, 
3859                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3860
3861         if (tb->subtypes) {
3862                 MonoDynamicTable *ntable;
3863                 
3864                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3865                 ntable->rows += mono_array_length (tb->subtypes);
3866                 alloc_table (ntable, ntable->rows);
3867                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3868
3869                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3870                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3871
3872                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3873                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3874                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3875                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3876                                 mono_string_to_utf8 (tb->name), tb->table_idx,
3877                                 ntable->next_idx, ntable->rows);*/
3878                         values += MONO_NESTED_CLASS_SIZE;
3879                         ntable->next_idx++;
3880                 }
3881         }
3882
3883         return TRUE;
3884 }
3885 #endif
3886
3887 static void
3888 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3889 {
3890         int i;
3891
3892         mono_ptr_array_append (*types, type);
3893
3894         if (!type->subtypes)
3895                 return;
3896
3897         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3898                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3899                 collect_types (types, subtype);
3900         }
3901 }
3902
3903 static gint
3904 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3905 {
3906         if ((*type1)->table_idx < (*type2)->table_idx)
3907                 return -1;
3908         else
3909                 if ((*type1)->table_idx > (*type2)->table_idx)
3910                         return 1;
3911         else
3912                 return 0;
3913 }
3914
3915 static gboolean
3916 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo, MonoError *error) {
3917         int i;
3918
3919         mono_error_init (error);
3920         if (!pinfo)
3921                 return TRUE;
3922         for (i = 0; i < mono_array_length (pinfo); ++i) {
3923                 MonoReflectionParamBuilder *pb;
3924                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3925                 if (!pb)
3926                         continue;
3927                 if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs, error))
3928                         return FALSE;
3929         }
3930
3931         return TRUE;
3932 }
3933
3934 static gboolean
3935 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error) {
3936         int i;
3937
3938         mono_error_init (error);
3939         
3940         if (!mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs, error))
3941                 return FALSE;
3942         if (tb->fields) {
3943                 for (i = 0; i < tb->num_fields; ++i) {
3944                         MonoReflectionFieldBuilder* fb;
3945                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3946                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
3947                                 return FALSE;
3948                 }
3949         }
3950         if (tb->events) {
3951                 for (i = 0; i < mono_array_length (tb->events); ++i) {
3952                         MonoReflectionEventBuilder* eb;
3953                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3954                         if (!mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs, error))
3955                                 return FALSE;
3956                 }
3957         }
3958         if (tb->properties) {
3959                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3960                         MonoReflectionPropertyBuilder* pb;
3961                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3962                         if (!mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs, error))
3963                                 return FALSE;
3964                 }
3965         }
3966         if (tb->ctors) {
3967                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3968                         MonoReflectionCtorBuilder* cb;
3969                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3970                         if (!mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs, error) ||
3971                             !params_add_cattrs (assembly, cb->pinfo, error))
3972                                 return FALSE;
3973                 }
3974         }
3975
3976         if (tb->methods) {
3977                 for (i = 0; i < tb->num_methods; ++i) {
3978                         MonoReflectionMethodBuilder* mb;
3979                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3980                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
3981                             !params_add_cattrs (assembly, mb->pinfo, error))
3982                                 return FALSE;
3983                 }
3984         }
3985
3986         if (tb->subtypes) {
3987                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3988                         if (!type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), error))
3989                                 return FALSE;
3990                 }
3991         }
3992
3993         return TRUE;
3994 }
3995
3996 static gboolean
3997 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb, MonoError *error)
3998 {
3999         int i;
4000         
4001         mono_error_init (error);
4002
4003         if (!mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs, error))
4004                 return FALSE;
4005
4006         if (moduleb->global_methods) {
4007                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4008                         MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4009                         if (!mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs, error) ||
4010                             !params_add_cattrs (assembly, mb->pinfo, error))
4011                                 return FALSE;
4012                 }
4013         }
4014
4015         if (moduleb->global_fields) {
4016                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
4017                         MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
4018                         if (!mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs, error))
4019                                 return FALSE;
4020                 }
4021         }
4022         
4023         if (moduleb->types) {
4024                 for (i = 0; i < moduleb->num_types; ++i) {
4025                         if (!type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i), error))
4026                                 return FALSE;
4027                 }
4028         }
4029
4030         return TRUE;
4031 }
4032
4033 static void
4034 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
4035 {
4036         MonoDynamicTable *table;
4037         guint32 *values;
4038         char blob_size [6];
4039         guchar hash [20];
4040         char *b = blob_size;
4041         char *dir, *path;
4042
4043         table = &assembly->tables [MONO_TABLE_FILE];
4044         table->rows++;
4045         alloc_table (table, table->rows);
4046         values = table->values + table->next_idx * MONO_FILE_SIZE;
4047         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
4048         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
4049         if (image_is_dynamic (module->image)) {
4050                 /* This depends on the fact that the main module is emitted last */
4051                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
4052                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
4053         } else {
4054                 dir = NULL;
4055                 path = g_strdup (module->image->name);
4056         }
4057         mono_sha1_get_digest_from_file (path, hash);
4058         g_free (dir);
4059         g_free (path);
4060         mono_metadata_encode_value (20, b, &b);
4061         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4062         mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4063         table->next_idx ++;
4064 }
4065
4066 static void
4067 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
4068 {
4069         MonoDynamicTable *table;
4070         int i;
4071
4072         table = &assembly->tables [MONO_TABLE_MODULE];
4073         mb->table_idx = table->next_idx ++;
4074         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
4075         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
4076         i /= 16;
4077         ++i;
4078         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
4079         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
4080         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
4081         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
4082 }
4083
4084 static guint32
4085 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
4086         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4087 {
4088         MonoDynamicTable *table;
4089         guint32 *values;
4090         guint32 visib, res;
4091
4092         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4093         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
4094                 return 0;
4095
4096         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4097         table->rows++;
4098         alloc_table (table, table->rows);
4099         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
4100
4101         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
4102         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
4103         if (klass->nested_in)
4104                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4105         else
4106                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
4107         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4108         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4109
4110         res = table->next_idx;
4111
4112         table->next_idx ++;
4113
4114         /* Emit nested types */
4115         if (klass->ext && klass->ext->nested_classes) {
4116                 GList *tmp;
4117
4118                 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
4119                         mono_image_fill_export_table_from_class (domain, (MonoClass *)tmp->data, module_index, table->next_idx - 1, assembly);
4120         }
4121
4122         return res;
4123 }
4124
4125 static void
4126 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
4127         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
4128 {
4129         MonoClass *klass;
4130         guint32 idx, i;
4131
4132         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
4133
4134         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
4135
4136         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
4137                                                                                                    parent_index, assembly);
4138
4139         /* 
4140          * Emit nested types
4141          * We need to do this ourselves since klass->nested_classes is not set up.
4142          */
4143         if (tb->subtypes) {
4144                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
4145                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
4146         }
4147 }
4148
4149 static void
4150 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
4151         guint32 module_index, MonoDynamicImage *assembly)
4152 {
4153         MonoImage *image = module->image;
4154         MonoTableInfo  *t;
4155         guint32 i;
4156
4157         t = &image->tables [MONO_TABLE_TYPEDEF];
4158
4159         for (i = 0; i < t->rows; ++i) {
4160                 MonoError error;
4161                 MonoClass *klass = mono_class_get_checked (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1), &error);
4162                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4163
4164                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
4165                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
4166         }
4167 }
4168
4169 static void
4170 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
4171 {
4172         MonoDynamicTable *table;
4173         guint32 *values;
4174         guint32 scope, scope_idx, impl, current_idx;
4175         gboolean forwarder = TRUE;
4176         gpointer iter = NULL;
4177         MonoClass *nested;
4178
4179         if (klass->nested_in) {
4180                 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
4181                 forwarder = FALSE;
4182         } else {
4183                 scope = resolution_scope_from_image (assembly, klass->image);
4184                 g_assert ((scope & MONO_RESOLUTION_SCOPE_MASK) == MONO_RESOLUTION_SCOPE_ASSEMBLYREF);
4185                 scope_idx = scope >> MONO_RESOLUTION_SCOPE_BITS;
4186                 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
4187         }
4188
4189         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
4190
4191         table->rows++;
4192         alloc_table (table, table->rows);
4193         current_idx = table->next_idx;
4194         values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
4195
4196         values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
4197         values [MONO_EXP_TYPE_TYPEDEF] = 0;
4198         values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
4199         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
4200         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
4201
4202         table->next_idx++;
4203
4204         while ((nested = mono_class_get_nested_types (klass, &iter)))
4205                 add_exported_type (assemblyb, assembly, nested, current_idx);
4206 }
4207
4208 static void
4209 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
4210 {
4211         MonoClass *klass;
4212         int i;
4213
4214         if (!assemblyb->type_forwarders)
4215                 return;
4216
4217         for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
4218                 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
4219                 MonoType *type;
4220                 if (!t)
4221                         continue;
4222
4223                 type = mono_reflection_type_get_handle (t);
4224                 g_assert (type);
4225
4226                 klass = mono_class_from_mono_type (type);
4227
4228                 add_exported_type (assemblyb, assembly, klass, 0);
4229         }
4230 }
4231
4232 #define align_pointer(base,p)\
4233         do {\
4234                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
4235                 if (__diff & 3)\
4236                         (p) += 4 - (__diff & 3);\
4237         } while (0)
4238
4239 static int
4240 compare_constants (const void *a, const void *b)
4241 {
4242         const guint32 *a_values = (const guint32 *)a;
4243         const guint32 *b_values = (const guint32 *)b;
4244         return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
4245 }
4246
4247 static int
4248 compare_semantics (const void *a, const void *b)
4249 {
4250         const guint32 *a_values = (const guint32 *)a;
4251         const guint32 *b_values = (const guint32 *)b;
4252         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
4253         if (assoc)
4254                 return assoc;
4255         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
4256 }
4257
4258 static int
4259 compare_custom_attrs (const void *a, const void *b)
4260 {
4261         const guint32 *a_values = (const guint32 *)a;
4262         const guint32 *b_values = (const guint32 *)b;
4263
4264         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
4265 }
4266
4267 static int
4268 compare_field_marshal (const void *a, const void *b)
4269 {
4270         const guint32 *a_values = (const guint32 *)a;
4271         const guint32 *b_values = (const guint32 *)b;
4272
4273         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
4274 }
4275
4276 static int
4277 compare_nested (const void *a, const void *b)
4278 {
4279         const guint32 *a_values = (const guint32 *)a;
4280         const guint32 *b_values = (const guint32 *)b;
4281
4282         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
4283 }
4284
4285 static int
4286 compare_genericparam (const void *a, const void *b)
4287 {
4288         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
4289         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
4290
4291         if ((*b_entry)->owner == (*a_entry)->owner)
4292                 return 
4293                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
4294                         mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
4295         else
4296                 return (*a_entry)->owner - (*b_entry)->owner;
4297 }
4298
4299 static int
4300 compare_declsecurity_attrs (const void *a, const void *b)
4301 {
4302         const guint32 *a_values = (const guint32 *)a;
4303         const guint32 *b_values = (const guint32 *)b;
4304
4305         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
4306 }
4307
4308 static int
4309 compare_interface_impl (const void *a, const void *b)
4310 {
4311         const guint32 *a_values = (const guint32 *)a;
4312         const guint32 *b_values = (const guint32 *)b;
4313
4314         int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
4315         if (klass)
4316                 return klass;
4317
4318         return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
4319 }
4320
4321 static void
4322 pad_heap (MonoDynamicStream *sh)
4323 {
4324         if (sh->index & 3) {
4325                 int sz = 4 - (sh->index & 3);
4326                 memset (sh->data + sh->index, 0, sz);
4327                 sh->index += sz;
4328         }
4329 }
4330
4331 struct StreamDesc {
4332         const char *name;
4333         MonoDynamicStream *stream;
4334 };
4335
4336 /*
4337  * build_compressed_metadata() fills in the blob of data that represents the 
4338  * raw metadata as it will be saved in the PE file. The five streams are output 
4339  * and the metadata tables are comnpressed from the guint32 array representation, 
4340  * to the compressed on-disk format.
4341  */
4342 static gboolean
4343 build_compressed_metadata (MonoDynamicImage *assembly, MonoError *error)
4344 {
4345         MonoDynamicTable *table;
4346         int i;
4347         guint64 valid_mask = 0;
4348         guint64 sorted_mask;
4349         guint32 heapt_size = 0;
4350         guint32 meta_size = 256; /* allow for header and other stuff */
4351         guint32 table_offset;
4352         guint32 ntables = 0;
4353         guint64 *int64val;
4354         guint32 *int32val;
4355         guint16 *int16val;
4356         MonoImage *meta;
4357         unsigned char *p;
4358         struct StreamDesc stream_desc [5];
4359
4360         mono_error_init (error);
4361
4362         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
4363         for (i = 0; i < assembly->gen_params->len; i++) {
4364                 GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (assembly->gen_params, i);
4365                 if (!write_generic_param_entry (assembly, entry, error))
4366                         return FALSE;
4367         }
4368
4369         stream_desc [0].name  = "#~";
4370         stream_desc [0].stream = &assembly->tstream;
4371         stream_desc [1].name  = "#Strings";
4372         stream_desc [1].stream = &assembly->sheap;
4373         stream_desc [2].name  = "#US";
4374         stream_desc [2].stream = &assembly->us;
4375         stream_desc [3].name  = "#Blob";
4376         stream_desc [3].stream = &assembly->blob;
4377         stream_desc [4].name  = "#GUID";
4378         stream_desc [4].stream = &assembly->guid;
4379         
4380         /* tables that are sorted */
4381         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4382                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4383                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4384                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4385                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4386                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4387                 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4388         
4389         /* Compute table sizes */
4390         /* the MonoImage has already been created in mono_image_basic_init() */
4391         meta = &assembly->image;
4392
4393         /* sizes should be multiple of 4 */
4394         pad_heap (&assembly->blob);
4395         pad_heap (&assembly->guid);
4396         pad_heap (&assembly->sheap);
4397         pad_heap (&assembly->us);
4398
4399         /* Setup the info used by compute_sizes () */
4400         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4401         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4402         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4403
4404         meta_size += assembly->blob.index;
4405         meta_size += assembly->guid.index;
4406         meta_size += assembly->sheap.index;
4407         meta_size += assembly->us.index;
4408
4409         for (i=0; i < MONO_TABLE_NUM; ++i)
4410                 meta->tables [i].rows = assembly->tables [i].rows;
4411         
4412         for (i = 0; i < MONO_TABLE_NUM; i++){
4413                 if (meta->tables [i].rows == 0)
4414                         continue;
4415                 valid_mask |= (guint64)1 << i;
4416                 ntables ++;
4417                 meta->tables [i].row_size = mono_metadata_compute_size (
4418                         meta, i, &meta->tables [i].size_bitfield);
4419                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4420         }
4421         heapt_size += 24; /* #~ header size */
4422         heapt_size += ntables * 4;
4423         /* make multiple of 4 */
4424         heapt_size += 3;
4425         heapt_size &= ~3;
4426         meta_size += heapt_size;
4427         meta->raw_metadata = (char *)g_malloc0 (meta_size);
4428         p = (unsigned char*)meta->raw_metadata;
4429         /* the metadata signature */
4430         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4431         /* version numbers and 4 bytes reserved */
4432         int16val = (guint16*)p;
4433         *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4434         *int16val = GUINT16_TO_LE (meta->md_version_minor);
4435         p += 8;
4436         /* version string */
4437         int32val = (guint32*)p;
4438         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4439         p += 4;
4440         memcpy (p, meta->version, strlen (meta->version));
4441         p += GUINT32_FROM_LE (*int32val);
4442         align_pointer (meta->raw_metadata, p);
4443         int16val = (guint16*)p;
4444         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4445         *int16val = GUINT16_TO_LE (5); /* number of streams */
4446         p += 4;
4447
4448         /*
4449          * write the stream info.
4450          */
4451         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4452         table_offset += 3; table_offset &= ~3;
4453
4454         assembly->tstream.index = heapt_size;
4455         for (i = 0; i < 5; ++i) {
4456                 int32val = (guint32*)p;
4457                 stream_desc [i].stream->offset = table_offset;
4458                 *int32val++ = GUINT32_TO_LE (table_offset);
4459                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4460                 table_offset += GUINT32_FROM_LE (*int32val);
4461                 table_offset += 3; table_offset &= ~3;
4462                 p += 8;
4463                 strcpy ((char*)p, stream_desc [i].name);
4464                 p += strlen (stream_desc [i].name) + 1;
4465                 align_pointer (meta->raw_metadata, p);
4466         }
4467         /* 
4468          * now copy the data, the table stream header and contents goes first.
4469          */
4470         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4471         p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4472         int32val = (guint32*)p;
4473         *int32val = GUINT32_TO_LE (0); /* reserved */
4474         p += 4;
4475
4476         *p++ = 2; /* version */
4477         *p++ = 0;
4478
4479         if (meta->idx_string_wide)
4480                 *p |= 0x01;
4481         if (meta->idx_guid_wide)
4482                 *p |= 0x02;
4483         if (meta->idx_blob_wide)
4484                 *p |= 0x04;
4485         ++p;
4486         *p++ = 1; /* reserved */
4487         int64val = (guint64*)p;
4488         *int64val++ = GUINT64_TO_LE (valid_mask);
4489         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
4490         p += 16;
4491         int32val = (guint32*)p;
4492         for (i = 0; i < MONO_TABLE_NUM; i++){
4493                 if (meta->tables [i].rows == 0)
4494                         continue;
4495                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4496         }
4497         p = (unsigned char*)int32val;
4498
4499         /* sort the tables that still need sorting */
4500         table = &assembly->tables [MONO_TABLE_CONSTANT];
4501         if (table->rows)
4502                 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4503         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4504         if (table->rows)
4505                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4506         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4507         if (table->rows)
4508                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4509         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4510         if (table->rows)
4511                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4512         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4513         if (table->rows)
4514                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4515         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4516         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4517         if (table->rows)
4518                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4519         table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4520         if (table->rows)
4521                 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4522
4523         /* compress the tables */
4524         for (i = 0; i < MONO_TABLE_NUM; i++){
4525                 int row, col;
4526                 guint32 *values;
4527                 guint32 bitfield = meta->tables [i].size_bitfield;
4528                 if (!meta->tables [i].rows)
4529                         continue;
4530                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4531                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4532                 meta->tables [i].base = (char*)p;
4533                 for (row = 1; row <= meta->tables [i].rows; ++row) {
4534                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
4535                         for (col = 0; col < assembly->tables [i].columns; ++col) {
4536                                 switch (mono_metadata_table_size (bitfield, col)) {
4537                                 case 1:
4538                                         *p++ = values [col];
4539                                         break;
4540                                 case 2:
4541                                         *p++ = values [col] & 0xff;
4542                                         *p++ = (values [col] >> 8) & 0xff;
4543                                         break;
4544                                 case 4:
4545                                         *p++ = values [col] & 0xff;
4546                                         *p++ = (values [col] >> 8) & 0xff;
4547                                         *p++ = (values [col] >> 16) & 0xff;
4548                                         *p++ = (values [col] >> 24) & 0xff;
4549                                         break;
4550                                 default:
4551                                         g_assert_not_reached ();
4552                                 }
4553                         }
4554                 }
4555                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4556         }
4557         
4558         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4559         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4560         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4561         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4562         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4563
4564         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4565
4566         return TRUE;
4567 }
4568
4569 /*
4570  * Some tables in metadata need to be sorted according to some criteria, but
4571  * when methods and fields are first created with reflection, they may be assigned a token
4572  * that doesn't correspond to the final token they will get assigned after the sorting.
4573  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4574  * with the reflection objects that represent them. Once all the tables are set up, the 
4575  * reflection objects will contains the correct table index. fixup_method() will fixup the
4576  * tokens for the method with ILGenerator @ilgen.
4577  */
4578 static void
4579 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4580 {
4581         guint32 code_idx = GPOINTER_TO_UINT (value);
4582         MonoReflectionILTokenInfo *iltoken;
4583         MonoReflectionFieldBuilder *field;
4584         MonoReflectionCtorBuilder *ctor;
4585         MonoReflectionMethodBuilder *method;
4586         MonoReflectionTypeBuilder *tb;
4587         MonoReflectionArrayMethod *am;
4588         guint32 i, idx = 0;
4589         unsigned char *target;
4590
4591         for (i = 0; i < ilgen->num_token_fixups; ++i) {
4592                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4593                 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4594                 switch (target [3]) {
4595                 case MONO_TABLE_FIELD:
4596                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4597                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
4598                                 idx = field->table_idx;
4599                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4600                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4601                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4602                         } else {
4603                                 g_assert_not_reached ();
4604                         }
4605                         break;
4606                 case MONO_TABLE_METHOD:
4607                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4608                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
4609                                 idx = method->table_idx;
4610                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4611                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4612                                 idx = ctor->table_idx;
4613                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
4614                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4615                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4616                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4617                         } else {
4618                                 g_assert_not_reached ();
4619                         }
4620                         break;
4621                 case MONO_TABLE_TYPEDEF:
4622                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4623                                 g_assert_not_reached ();
4624                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
4625                         idx = tb->table_idx;
4626                         break;
4627                 case MONO_TABLE_MEMBERREF:
4628                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4629                                 am = (MonoReflectionArrayMethod*)iltoken->member;
4630                                 idx = am->table_idx;
4631                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4632                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4633                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4634                                    !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4635                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4636                                 g_assert (m->klass->generic_class || m->klass->generic_container);
4637                                 continue;
4638                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4639                                 continue;
4640                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4641                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4642                                 g_assert (is_field_on_inst (f));
4643                                 continue;
4644                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4645                                         !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4646                                 continue;
4647                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4648                                 continue;
4649                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4650                                 continue;
4651                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4652                                 continue;
4653                         } else {
4654                                 g_assert_not_reached ();
4655                         }
4656                         break;
4657                 case MONO_TABLE_METHODSPEC:
4658                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4659                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4660                                 g_assert (mono_method_signature (m)->generic_param_count);
4661                                 continue;
4662                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4663                                 continue;
4664                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4665                                 continue;
4666                         } else {
4667                                 g_assert_not_reached ();
4668                         }
4669                         break;
4670                 default:
4671                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
4672                 }
4673                 target [0] = idx & 0xff;
4674                 target [1] = (idx >> 8) & 0xff;
4675                 target [2] = (idx >> 16) & 0xff;
4676         }
4677 }
4678
4679 /*
4680  * fixup_cattrs:
4681  *
4682  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4683  * value is not known when the table is emitted.
4684  */
4685 static void
4686 fixup_cattrs (MonoDynamicImage *assembly)
4687 {
4688         MonoDynamicTable *table;
4689         guint32 *values;
4690         guint32 type, i, idx, token;
4691         MonoObject *ctor;
4692
4693         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4694
4695         for (i = 0; i < table->rows; ++i) {
4696                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4697
4698                 type = values [MONO_CUSTOM_ATTR_TYPE];
4699                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4700                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4701                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4702                         ctor = (MonoObject *)mono_g_hash_table_lookup (assembly->remapped_tokens, GUINT_TO_POINTER (token));
4703                         g_assert (ctor);
4704
4705                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4706                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4707                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4708                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4709                         } else if (!strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4710                                 MonoMethod *m = ((MonoReflectionCtorBuilder*)ctor)->mhandle;
4711                                 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4712                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4713                         }
4714                 }
4715         }
4716 }
4717
4718 static void
4719 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4720 {
4721         MonoDynamicTable *table;
4722         guint32 *values;
4723
4724         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4725         table->rows++;
4726         alloc_table (table, table->rows);
4727         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4728         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4729         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4730         values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4731         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4732         table->next_idx++;
4733 }
4734
4735 static void
4736 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4737 {
4738         MonoDynamicTable *table;
4739         guint32 *values;
4740         char blob_size [6];
4741         guchar hash [20];
4742         char *b = blob_size;
4743         char *name, *sname;
4744         guint32 idx, offset;
4745
4746         if (rsrc->filename) {
4747                 name = mono_string_to_utf8 (rsrc->filename);
4748                 sname = g_path_get_basename (name);
4749         
4750                 table = &assembly->tables [MONO_TABLE_FILE];
4751                 table->rows++;
4752                 alloc_table (table, table->rows);
4753                 values = table->values + table->next_idx * MONO_FILE_SIZE;
4754                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4755                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4756                 g_free (sname);
4757
4758                 mono_sha1_get_digest_from_file (name, hash);
4759                 mono_metadata_encode_value (20, b, &b);
4760                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4761                 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4762                 g_free (name);
4763                 idx = table->next_idx++;
4764                 rsrc->offset = 0;
4765                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4766         } else {
4767                 char sizebuf [4];
4768                 char *data;
4769                 guint len;
4770                 if (rsrc->data) {
4771                         data = mono_array_addr (rsrc->data, char, 0);
4772                         len = mono_array_length (rsrc->data);
4773                 } else {
4774                         data = NULL;
4775                         len = 0;
4776                 }
4777                 offset = len;
4778                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4779                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4780                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4781                 mono_image_add_stream_data (&assembly->resources, data, len);
4782
4783                 if (!mb->is_main)
4784                         /* 
4785                          * The entry should be emitted into the MANIFESTRESOURCE table of 
4786                          * the main module, but that needs to reference the FILE table
4787                          * which isn't emitted yet.
4788                          */
4789                         return;
4790                 else
4791                         idx = 0;
4792         }
4793
4794         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4795 }
4796
4797 static void
4798 set_version_from_string (MonoString *version, guint32 *values)
4799 {
4800         gchar *ver, *p, *str;
4801         guint32 i;
4802         
4803         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4804         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4805         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4806         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4807         if (!version)
4808                 return;
4809         ver = str = mono_string_to_utf8 (version);
4810         for (i = 0; i < 4; ++i) {
4811                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4812                 switch (*p) {
4813                 case '.':
4814                         p++;
4815                         break;
4816                 case '*':
4817                         /* handle Revision and Build */
4818                         p++;
4819                         break;
4820                 }
4821                 ver = p;
4822         }
4823         g_free (str);
4824 }
4825
4826 static guint32
4827 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4828         gsize len;
4829         guint32 token = 0;
4830         char blob_size [6];
4831         char *b = blob_size;
4832
4833         if (!pkey)
4834                 return token;
4835
4836         len = mono_array_length (pkey);
4837         mono_metadata_encode_value (len, b, &b);
4838         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4839         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4840
4841         assembly->public_key = (guint8 *)g_malloc (len);
4842         memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4843         assembly->public_key_len = len;
4844
4845         /* Special case: check for ECMA key (16 bytes) */
4846         if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4847                 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4848                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4849         } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4850                 /* minimum key size (in 2.0) is 384 bits */
4851                 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4852         } else {
4853                 /* FIXME - verifier */
4854                 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4855                 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4856         }
4857         assembly->strong_name = (char *)g_malloc0 (assembly->strong_name_size);
4858
4859         return token;
4860 }
4861
4862 static void
4863 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4864 {
4865         MonoDynamicTable *table;
4866         MonoDynamicImage *assembly;
4867         MonoReflectionAssemblyBuilder *assemblyb;
4868         MonoDomain *domain;
4869         guint32 *values;
4870         int i;
4871         guint32 module_index;
4872
4873         assemblyb = moduleb->assemblyb;
4874         assembly = moduleb->dynamic_image;
4875         domain = mono_object_domain (assemblyb);
4876
4877         /* Emit ASSEMBLY table */
4878         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4879         alloc_table (table, 1);
4880         values = table->values + MONO_ASSEMBLY_SIZE;
4881         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4882         values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4883         if (assemblyb->culture) {
4884                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4885         } else {
4886                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4887         }
4888         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4889         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4890         set_version_from_string (assemblyb->version, values);
4891
4892         /* Emit FILE + EXPORTED_TYPE table */
4893         module_index = 0;
4894         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4895                 int j;
4896                 MonoReflectionModuleBuilder *file_module = 
4897                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4898                 if (file_module != moduleb) {
4899                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4900                         module_index ++;
4901                         if (file_module->types) {
4902                                 for (j = 0; j < file_module->num_types; ++j) {
4903                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4904                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4905                                 }
4906                         }
4907                 }
4908         }
4909         if (assemblyb->loaded_modules) {
4910                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4911                         MonoReflectionModule *file_module = 
4912                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4913                         mono_image_fill_file_table (domain, file_module, assembly);
4914                         module_index ++;
4915                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4916                 }
4917         }
4918         if (assemblyb->type_forwarders)
4919                 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4920
4921         /* Emit MANIFESTRESOURCE table */
4922         module_index = 0;
4923         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4924                 int j;
4925                 MonoReflectionModuleBuilder *file_module = 
4926                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4927                 /* The table for the main module is emitted later */
4928                 if (file_module != moduleb) {
4929                         module_index ++;
4930                         if (file_module->resources) {
4931                                 int len = mono_array_length (file_module->resources);
4932                                 for (j = 0; j < len; ++j) {
4933                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4934                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4935                                 }
4936                         }
4937                 }
4938         }               
4939 }
4940
4941 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4942
4943 /*
4944  * mono_image_build_metadata() will fill the info in all the needed metadata tables
4945  * for the modulebuilder @moduleb.
4946  * At the end of the process, method and field tokens are fixed up and the 
4947  * on-disk compressed metadata representation is created.
4948  * Return TRUE on success, or FALSE on failure and sets @error
4949  */
4950 gboolean
4951 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
4952 {
4953         MonoDynamicTable *table;
4954         MonoDynamicImage *assembly;
4955         MonoReflectionAssemblyBuilder *assemblyb;
4956         MonoDomain *domain;
4957         MonoPtrArray types;
4958         guint32 *values;
4959         int i, j;
4960
4961         mono_error_init (error);
4962
4963         assemblyb = moduleb->assemblyb;
4964         assembly = moduleb->dynamic_image;
4965         domain = mono_object_domain (assemblyb);
4966
4967         if (assembly->text_rva)
4968                 return TRUE;
4969
4970         assembly->text_rva = START_TEXT_RVA;
4971
4972         if (moduleb->is_main) {
4973                 mono_image_emit_manifest (moduleb);
4974         }
4975
4976         table = &assembly->tables [MONO_TABLE_TYPEDEF];
4977         table->rows = 1; /* .<Module> */
4978         table->next_idx++;
4979         alloc_table (table, table->rows);
4980         /*
4981          * Set the first entry.
4982          */
4983         values = table->values + table->columns;
4984         values [MONO_TYPEDEF_FLAGS] = 0;
4985         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4986         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4987         values [MONO_TYPEDEF_EXTENDS] = 0;
4988         values [MONO_TYPEDEF_FIELD_LIST] = 1;
4989         values [MONO_TYPEDEF_METHOD_LIST] = 1;
4990
4991         /* 
4992          * handle global methods 
4993          * FIXME: test what to do when global methods are defined in multiple modules.
4994          */
4995         if (moduleb->global_methods) {
4996                 table = &assembly->tables [MONO_TABLE_METHOD];
4997                 table->rows += mono_array_length (moduleb->global_methods);
4998                 alloc_table (table, table->rows);
4999                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5000                         if (!mono_image_get_method_info (
5001                                     mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly, error))
5002                                 goto leave;
5003                 }
5004         }
5005         if (moduleb->global_fields) {
5006                 table = &assembly->tables [MONO_TABLE_FIELD];
5007                 table->rows += mono_array_length (moduleb->global_fields);
5008                 alloc_table (table, table->rows);
5009                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
5010                         mono_image_get_field_info (
5011                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
5012         }
5013
5014         table = &assembly->tables [MONO_TABLE_MODULE];
5015         alloc_table (table, 1);
5016         mono_image_fill_module_table (domain, moduleb, assembly);
5017
5018         /* Collect all types into a list sorted by their table_idx */
5019         mono_ptr_array_init (types, moduleb->num_types, MONO_ROOT_SOURCE_REFLECTION, "dynamic module types list");
5020
5021         if (moduleb->types)
5022                 for (i = 0; i < moduleb->num_types; ++i) {
5023                         MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
5024                         collect_types (&types, type);
5025                 }
5026
5027         mono_ptr_array_sort (types, (int (*)(const void *, const void *))compare_types_by_table_idx);
5028         table = &assembly->tables [MONO_TABLE_TYPEDEF];
5029         table->rows += mono_ptr_array_size (types);
5030         alloc_table (table, table->rows);
5031
5032         /*
5033          * Emit type names + namespaces at one place inside the string heap,
5034          * so load_class_names () needs to touch fewer pages.
5035          */
5036         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5037                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5038                 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
5039         }
5040         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5041                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5042                 string_heap_insert_mstring (&assembly->sheap, tb->name);
5043         }
5044
5045         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5046                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5047                 if (!mono_image_get_type_info (domain, type, assembly, error))
5048                         goto leave_types;
5049         }
5050
5051         /* 
5052          * table->rows is already set above and in mono_image_fill_module_table.
5053          */
5054         /* add all the custom attributes at the end, once all the indexes are stable */
5055         if (!mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs, error))
5056                 goto leave_types;
5057
5058         /* CAS assembly permissions */
5059         if (assemblyb->permissions_minimum)
5060                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
5061         if (assemblyb->permissions_optional)
5062                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
5063         if (assemblyb->permissions_refused)
5064                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
5065
5066         if (!module_add_cattrs (assembly, moduleb, error))
5067                 goto leave_types;
5068
5069         /* fixup tokens */
5070         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
5071
5072         /* Create the MethodImpl table.  We do this after emitting all methods so we already know
5073          * the final tokens and don't need another fixup pass. */
5074
5075         if (moduleb->global_methods) {
5076                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
5077                         MonoReflectionMethodBuilder *mb = mono_array_get (
5078                                 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
5079                         if (!mono_image_add_methodimpl (assembly, mb, error))
5080                                 goto leave_types;
5081                 }
5082         }
5083
5084         for (i = 0; i < mono_ptr_array_size (types); ++i) {
5085                 MonoReflectionTypeBuilder *type = (MonoReflectionTypeBuilder *)mono_ptr_array_get (types, i);
5086                 if (type->methods) {
5087                         for (j = 0; j < type->num_methods; ++j) {
5088                                 MonoReflectionMethodBuilder *mb = mono_array_get (
5089                                         type->methods, MonoReflectionMethodBuilder*, j);
5090
5091                                 if (!mono_image_add_methodimpl (assembly, mb, error))
5092                                         goto leave_types;
5093                         }
5094                 }
5095         }
5096
5097         fixup_cattrs (assembly);
5098
5099 leave_types:
5100         mono_ptr_array_destroy (types);
5101 leave:
5102
5103         return mono_error_ok (error);
5104 }
5105
5106 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5107
5108 gboolean
5109 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb, MonoError *error)
5110 {
5111         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
5112 }
5113
5114 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5115
5116
5117 typedef struct {
5118         guint32 import_lookup_table;
5119         guint32 timestamp;
5120         guint32 forwarder;
5121         guint32 name_rva;
5122         guint32 import_address_table_rva;
5123 } MonoIDT;
5124
5125 typedef struct {
5126         guint32 name_rva;
5127         guint32 flags;
5128 } MonoILT;
5129
5130 #ifndef DISABLE_REFLECTION_EMIT
5131
5132 /*
5133  * mono_image_insert_string:
5134  * @module: module builder object
5135  * @str: a string
5136  *
5137  * Insert @str into the user string stream of @module.
5138  */
5139 guint32
5140 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
5141 {
5142         MonoDynamicImage *assembly;
5143         guint32 idx;
5144         char buf [16];
5145         char *b = buf;
5146         
5147         if (!module->dynamic_image)
5148                 mono_image_module_basic_init (module);
5149
5150         assembly = module->dynamic_image;
5151         
5152         if (assembly->save) {
5153                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
5154                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
5155 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
5156         {
5157                 char *swapped = g_malloc (2 * mono_string_length (str));
5158                 const char *p = (const char*)mono_string_chars (str);
5159
5160                 swap_with_size (swapped, p, 2, mono_string_length (str));
5161                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
5162                 g_free (swapped);
5163         }
5164 #else
5165                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
5166 #endif
5167                 mono_image_add_stream_data (&assembly->us, "", 1);
5168         } else {
5169                 idx = assembly->us.index ++;
5170         }
5171
5172         register_dyn_token (assembly, MONO_TOKEN_STRING | idx, (MonoObject*)str);
5173
5174         return MONO_TOKEN_STRING | idx;
5175 }
5176
5177 guint32
5178 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
5179 {
5180         MonoClass *klass;
5181         guint32 token = 0;
5182         MonoMethodSignature *sig;
5183
5184         mono_error_init (error);
5185
5186         klass = obj->vtable->klass;
5187         if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
5188                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
5189                 MonoMethodSignature *old;
5190                 guint32 sig_token, parent;
5191                 int nargs, i;
5192
5193                 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
5194
5195                 nargs = mono_array_length (opt_param_types);
5196                 old = mono_method_signature (method);
5197                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
5198
5199                 sig->hasthis = old->hasthis;
5200                 sig->explicit_this = old->explicit_this;
5201                 sig->call_convention = old->call_convention;
5202                 sig->generic_param_count = old->generic_param_count;
5203                 sig->param_count = old->param_count + nargs;
5204                 sig->sentinelpos = old->param_count;
5205                 sig->ret = old->ret;
5206
5207                 for (i = 0; i < old->param_count; i++)
5208                         sig->params [i] = old->params [i];
5209
5210                 for (i = 0; i < nargs; i++) {
5211                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5212                         sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
5213                 }
5214
5215                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
5216                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
5217                 parent >>= MONO_TYPEDEFORREF_BITS;
5218
5219                 parent <<= MONO_MEMBERREF_PARENT_BITS;
5220                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
5221
5222                 sig_token = method_encode_signature (assembly, sig);
5223                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
5224         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
5225                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5226                 ReflectionMethodBuilder rmb;
5227                 guint32 parent, sig_token;
5228                 int nopt_args, nparams, ngparams, i;
5229
5230                 if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
5231                         goto fail;
5232                 
5233                 rmb.opt_types = opt_param_types;
5234                 nopt_args = mono_array_length (opt_param_types);
5235
5236                 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
5237                 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
5238                 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
5239
5240                 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
5241                 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
5242                 sig->call_convention = rmb.call_conv;
5243                 sig->generic_param_count = ngparams;
5244                 sig->param_count = nparams + nopt_args;
5245                 sig->sentinelpos = nparams;
5246                 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
5247
5248                 for (i = 0; i < nparams; i++) {
5249                         MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
5250                         sig->params [i] = mono_reflection_type_get_handle (rt);
5251                 }
5252
5253                 for (i = 0; i < nopt_args; i++) {
5254                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
5255                         sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
5256                 }
5257
5258                 sig_token = method_builder_encode_signature (assembly, &rmb);
5259
5260                 parent = mono_image_create_token (assembly, obj, TRUE, TRUE, error);
5261                 if (!mono_error_ok (error))
5262                         goto fail;
5263                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
5264
5265                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
5266                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
5267
5268                 char *name = mono_string_to_utf8 (rmb.name);
5269                 token = mono_image_get_varargs_method_token (
5270                         assembly, parent, name, sig_token);
5271                 g_free (name);
5272         } else {
5273                 g_error ("requested method token for %s\n", klass->name);
5274         }
5275
5276         g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
5277         register_dyn_token (assembly, token, obj);
5278         return token;
5279 fail:
5280         g_assert (!mono_error_ok (error));
5281         return 0;
5282 }
5283
5284 /*
5285  * mono_image_create_token:
5286  * @assembly: a dynamic assembly
5287  * @obj:
5288  * @register_token: Whenever to register the token in the assembly->tokens hash. 
5289  *
5290  * Get a token to insert in the IL code stream for the given MemberInfo.
5291  * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time, 
5292  * the table_idx-es were recomputed, so registering the token would overwrite an existing 
5293  * entry.
5294  */
5295 guint32
5296 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
5297                          gboolean create_open_instance, gboolean register_token,
5298                          MonoError *error)
5299 {
5300         MonoClass *klass;
5301         guint32 token = 0;
5302
5303         mono_error_init (error);
5304
5305         klass = obj->vtable->klass;
5306
5307         /* Check for user defined reflection objects */
5308         /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
5309         if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
5310                 mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported");
5311                 return 0;
5312         }
5313
5314         if (strcmp (klass->name, "MethodBuilder") == 0) {
5315                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5316                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5317
5318                 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
5319                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5320                 else {
5321                         token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance, error);
5322                         if (!mono_error_ok (error))
5323                                 return 0;
5324                 }
5325                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5326         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5327                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5328                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
5329
5330                 if (tb->module->dynamic_image == assembly && !tb->generic_params)
5331                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5332                 else {
5333                         token = mono_image_get_ctorbuilder_token (assembly, mb, error);
5334                         if (!mono_error_ok (error))
5335                                 return 0;
5336                 }
5337                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
5338         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5339                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5340                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5341                 if (tb->generic_params) {
5342                         token = mono_image_get_generic_field_token (assembly, fb);
5343                 } else {
5344                         if (tb->module->dynamic_image == assembly) {
5345                                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5346                         } else {
5347                                 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
5348                         }
5349                 }
5350         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5351                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5352                 if (create_open_instance && tb->generic_params) {
5353                         MonoType *type;
5354                         init_type_builder_generics (obj);
5355                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5356                         token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
5357                         token = mono_metadata_token_from_dor (token);
5358                 } else if (tb->module->dynamic_image == assembly) {
5359                         token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5360                 } else {
5361                         MonoType *type;
5362                         type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5363                         token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
5364                 }
5365         } else if (strcmp (klass->name, "MonoType") == 0) {
5366                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5367                 MonoClass *mc = mono_class_from_mono_type (type);
5368                 token = mono_metadata_token_from_dor (
5369                         mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
5370         } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
5371                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5372                 token = mono_metadata_token_from_dor (
5373                         mono_image_typedef_or_ref (assembly, type));
5374         } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
5375                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5376                 token = mono_metadata_token_from_dor (
5377                         mono_image_typedef_or_ref (assembly, type));
5378         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
5379                    strcmp (klass->name, "MonoMethod") == 0 ||
5380                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
5381                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
5382                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
5383                 if (m->method->is_inflated) {
5384                         if (create_open_instance)
5385                                 token = mono_image_get_methodspec_token (assembly, m->method);
5386                         else
5387                                 token = mono_image_get_inflated_method_token (assembly, m->method);
5388                 } else if ((m->method->klass->image == &assembly->image) &&
5389                          !m->method->klass->generic_class) {
5390                         static guint32 method_table_idx = 0xffffff;
5391                         if (m->method->klass->wastypebuilder) {
5392                                 /* we use the same token as the one that was assigned
5393                                  * to the Methodbuilder.
5394                                  * FIXME: do the equivalent for Fields.
5395                                  */
5396                                 token = m->method->token;
5397                         } else {
5398                                 /*
5399                                  * Each token should have a unique index, but the indexes are
5400                                  * assigned by managed code, so we don't know about them. An
5401                                  * easy solution is to count backwards...
5402                                  */
5403                                 method_table_idx --;
5404                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
5405                         }
5406                 } else {
5407                         token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
5408                 }
5409                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
5410         } else if (strcmp (klass->name, "MonoField") == 0) {
5411                 MonoReflectionField *f = (MonoReflectionField *)obj;
5412                 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5413                         static guint32 field_table_idx = 0xffffff;
5414                         field_table_idx --;
5415                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5416                 } else {
5417                         token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5418                 }
5419                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5420         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5421                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5422                 token = mono_image_get_array_token (assembly, m);
5423         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5424                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5425                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5426         } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5427                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5428                 token = mono_metadata_token_from_dor (
5429                         mono_image_typedef_or_ref (assembly, type));
5430         } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5431                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5432                 token = mono_image_get_field_on_inst_token (assembly, f);
5433         } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5434                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5435                 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance, error);
5436                 if (!mono_error_ok (error))
5437                         return 0;
5438         } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5439                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5440                 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance, error);
5441                 if (!mono_error_ok (error))
5442                         return 0;
5443         } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5444                 MonoReflectionType *type = (MonoReflectionType *)obj;
5445                 token = mono_metadata_token_from_dor (
5446                                 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5447         } else {
5448                 g_error ("requested token for %s\n", klass->name);
5449         }
5450
5451         if (register_token)
5452                 mono_image_register_token (assembly, token, obj);
5453
5454         return token;
5455 }
5456
5457 /*
5458  * mono_image_register_token:
5459  *
5460  *   Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5461  * the Module.ResolveXXXToken () methods to work.
5462  */
5463 void
5464 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5465 {
5466         MonoObject *prev;
5467
5468         dynamic_image_lock (assembly);
5469         prev = (MonoObject *)mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5470         if (prev) {
5471                 /* There could be multiple MethodInfo objects with the same token */
5472                 //g_assert (prev == obj);
5473         } else {
5474                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5475         }
5476         dynamic_image_unlock (assembly);
5477 }
5478
5479 static MonoDynamicImage*
5480 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5481 {
5482         static const guchar entrycode [16] = {0xff, 0x25, 0};
5483         MonoDynamicImage *image;
5484         int i;
5485
5486         const char *version;
5487
5488         if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5489                 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5490         else
5491                 version = mono_get_runtime_info ()->runtime_version;
5492
5493 #if HAVE_BOEHM_GC
5494         /* The MonoGHashTable's need GC tracking */
5495         image = (MonoDynamicImage *)GC_MALLOC (sizeof (MonoDynamicImage));
5496 #else
5497         image = g_new0 (MonoDynamicImage, 1);
5498 #endif
5499
5500         mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5501         
5502         /*g_print ("created image %p\n", image);*/
5503         /* keep in sync with image.c */
5504         image->image.name = assembly_name;
5505         image->image.assembly_name = image->image.name; /* they may be different */
5506         image->image.module_name = module_name;
5507         image->image.version = g_strdup (version);
5508         image->image.md_version_major = 1;
5509         image->image.md_version_minor = 1;
5510         image->image.dynamic = TRUE;
5511
5512         image->image.references = g_new0 (MonoAssembly*, 1);
5513         image->image.references [0] = NULL;
5514
5515         mono_image_init (&image->image);
5516
5517         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");
5518         image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5519         image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5520         image->method_aux_hash = g_hash_table_new (NULL, NULL);
5521         image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5522         image->handleref = g_hash_table_new (NULL, NULL);
5523         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");
5524         image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module tokens table");
5525         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");
5526         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");
5527         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5528         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5529         image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5530         image->gen_params = g_ptr_array_new ();
5531         image->remapped_tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_REFLECTION, "dynamic module remapped tokens table");
5532
5533         /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5534         string_heap_init (&image->sheap);
5535         mono_image_add_stream_data (&image->us, "", 1);
5536         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5537         /* import tables... */
5538         mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5539         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5540         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5541         image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5542         mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5543         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5544         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5545         stream_data_align (&image->code);
5546
5547         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5548
5549         for (i=0; i < MONO_TABLE_NUM; ++i) {
5550                 image->tables [i].next_idx = 1;
5551                 image->tables [i].columns = table_sizes [i];
5552         }
5553
5554         image->image.assembly = (MonoAssembly*)assembly;
5555         image->run = assembly->run;
5556         image->save = assembly->save;
5557         image->pe_kind = 0x1; /* ILOnly */
5558         image->machine = 0x14c; /* I386 */
5559         
5560         mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5561
5562         dynamic_images_lock ();
5563
5564         if (!dynamic_images)
5565                 dynamic_images = g_ptr_array_new ();
5566
5567         g_ptr_array_add (dynamic_images, image);
5568
5569         dynamic_images_unlock ();
5570
5571         return image;
5572 }
5573 #endif
5574
5575 static void
5576 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5577 {
5578         g_free (key);
5579 }
5580
5581 static void
5582 release_hashtable (MonoGHashTable **hash)
5583 {
5584         if (*hash) {
5585                 mono_g_hash_table_destroy (*hash);
5586                 *hash = NULL;
5587         }
5588 }
5589
5590 void
5591 mono_dynamic_image_release_gc_roots (MonoDynamicImage *image)
5592 {
5593         release_hashtable (&image->token_fixups);
5594         release_hashtable (&image->handleref_managed);
5595         release_hashtable (&image->tokens);
5596         release_hashtable (&image->remapped_tokens);
5597         release_hashtable (&image->generic_def_objects);
5598         release_hashtable (&image->methodspec);
5599 }
5600
5601 // Free dynamic image pass one: Free resources but not image itself
5602 void
5603 mono_dynamic_image_free (MonoDynamicImage *image)
5604 {
5605         MonoDynamicImage *di = image;
5606         GList *list;
5607         int i;
5608
5609         if (di->methodspec)
5610                 mono_g_hash_table_destroy (di->methodspec);
5611         if (di->typespec)
5612                 g_hash_table_destroy (di->typespec);
5613         if (di->typeref)
5614                 g_hash_table_destroy (di->typeref);
5615         if (di->handleref)
5616                 g_hash_table_destroy (di->handleref);
5617         if (di->handleref_managed)
5618                 mono_g_hash_table_destroy (di->handleref_managed);
5619         if (di->tokens)
5620                 mono_g_hash_table_destroy (di->tokens);
5621         if (di->remapped_tokens)
5622                 mono_g_hash_table_destroy (di->remapped_tokens);
5623         if (di->generic_def_objects)
5624                 mono_g_hash_table_destroy (di->generic_def_objects);
5625         if (di->blob_cache) {
5626                 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5627                 g_hash_table_destroy (di->blob_cache);
5628         }
5629         if (di->standalonesig_cache)
5630                 g_hash_table_destroy (di->standalonesig_cache);
5631         for (list = di->array_methods; list; list = list->next) {
5632                 ArrayMethod *am = (ArrayMethod *)list->data;
5633                 g_free (am->sig);
5634                 g_free (am->name);
5635                 g_free (am);
5636         }
5637         g_list_free (di->array_methods);
5638         if (di->gen_params) {
5639                 for (i = 0; i < di->gen_params->len; i++) {
5640                         GenericParamTableEntry *entry = (GenericParamTableEntry *)g_ptr_array_index (di->gen_params, i);
5641                         mono_gc_deregister_root ((char*) &entry->gparam);
5642                         g_free (entry);
5643                 }
5644                 g_ptr_array_free (di->gen_params, TRUE);
5645         }
5646         if (di->token_fixups)
5647                 mono_g_hash_table_destroy (di->token_fixups);
5648         if (di->method_to_table_idx)
5649                 g_hash_table_destroy (di->method_to_table_idx);
5650         if (di->field_to_table_idx)
5651                 g_hash_table_destroy (di->field_to_table_idx);
5652         if (di->method_aux_hash)
5653                 g_hash_table_destroy (di->method_aux_hash);
5654         if (di->vararg_aux_hash)
5655                 g_hash_table_destroy (di->vararg_aux_hash);
5656         g_free (di->strong_name);
5657         g_free (di->win32_res);
5658         if (di->public_key)
5659                 g_free (di->public_key);
5660
5661         /*g_print ("string heap destroy for image %p\n", di);*/
5662         mono_dynamic_stream_reset (&di->sheap);
5663         mono_dynamic_stream_reset (&di->code);
5664         mono_dynamic_stream_reset (&di->resources);
5665         mono_dynamic_stream_reset (&di->us);
5666         mono_dynamic_stream_reset (&di->blob);
5667         mono_dynamic_stream_reset (&di->tstream);
5668         mono_dynamic_stream_reset (&di->guid);
5669         for (i = 0; i < MONO_TABLE_NUM; ++i) {
5670                 g_free (di->tables [i].values);
5671         }
5672
5673         dynamic_images_lock ();
5674
5675         if (dynamic_images)
5676                 g_ptr_array_remove (dynamic_images, di);
5677
5678         dynamic_images_unlock ();
5679 }
5680
5681 // Free dynamic image pass two: Free image itself (might never get called in some debug modes)
5682 void
5683 mono_dynamic_image_free_image (MonoDynamicImage *image)
5684 {
5685         /* See create_dynamic_mono_image () */
5686 #if HAVE_BOEHM_GC
5687         /* Allocated using GC_MALLOC */
5688 #else
5689         g_free (image);
5690 #endif
5691 }
5692
5693 #ifndef DISABLE_REFLECTION_EMIT
5694
5695 /*
5696  * mono_image_basic_init:
5697  * @assembly: an assembly builder object
5698  *
5699  * Create the MonoImage that represents the assembly builder and setup some
5700  * of the helper hash table and the basic metadata streams.
5701  */
5702 void
5703 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5704 {
5705         MonoDynamicAssembly *assembly;
5706         MonoDynamicImage *image;
5707         MonoDomain *domain = mono_object_domain (assemblyb);
5708         
5709         if (assemblyb->dynamic_assembly)
5710                 return;
5711
5712 #if HAVE_BOEHM_GC
5713         /* assembly->assembly.image might be GC allocated */
5714         assembly = assemblyb->dynamic_assembly = (MonoDynamicAssembly *)GC_MALLOC (sizeof (MonoDynamicAssembly));
5715 #else
5716         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5717 #endif
5718
5719         mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5720         
5721         assembly->assembly.ref_count = 1;
5722         assembly->assembly.dynamic = TRUE;
5723         assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5724         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5725         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5726         if (assemblyb->culture)
5727                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5728         else
5729                 assembly->assembly.aname.culture = g_strdup ("");
5730
5731         if (assemblyb->version) {
5732                         char *vstr = mono_string_to_utf8 (assemblyb->version);
5733                         char **version = g_strsplit (vstr, ".", 4);
5734                         char **parts = version;
5735                         assembly->assembly.aname.major = atoi (*parts++);
5736                         assembly->assembly.aname.minor = atoi (*parts++);
5737                         assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5738                         assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5739
5740                         g_strfreev (version);
5741                         g_free (vstr);
5742         } else {
5743                         assembly->assembly.aname.major = 0;
5744                         assembly->assembly.aname.minor = 0;
5745                         assembly->assembly.aname.build = 0;
5746                         assembly->assembly.aname.revision = 0;
5747         }
5748
5749         assembly->run = assemblyb->access != 2;
5750         assembly->save = assemblyb->access != 1;
5751         assembly->domain = domain;
5752
5753         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5754         image->initial_image = TRUE;
5755         assembly->assembly.aname.name = image->image.name;
5756         assembly->assembly.image = &image->image;
5757         if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5758                 /* -1 to correct for the trailing NULL byte */
5759                 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5760                         g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5761                 }
5762                 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);           
5763         }
5764
5765         mono_domain_assemblies_lock (domain);
5766         domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
5767         mono_domain_assemblies_unlock (domain);
5768
5769         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5770         
5771         mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5772         
5773         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5774 }
5775
5776 #endif /* !DISABLE_REFLECTION_EMIT */
5777
5778 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5779
5780 static int
5781 calc_section_size (MonoDynamicImage *assembly)
5782 {
5783         int nsections = 0;
5784
5785         /* alignment constraints */
5786         mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5787         g_assert ((assembly->code.index % 4) == 0);
5788         assembly->meta_size += 3;
5789         assembly->meta_size &= ~3;
5790         mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5791         g_assert ((assembly->resources.index % 4) == 0);
5792
5793         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5794         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5795         nsections++;
5796
5797         if (assembly->win32_res) {
5798                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5799
5800                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5801                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5802                 nsections++;
5803         }
5804
5805         assembly->sections [MONO_SECTION_RELOC].size = 12;
5806         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5807         nsections++;
5808
5809         return nsections;
5810 }
5811
5812 typedef struct {
5813         guint32 id;
5814         guint32 offset;
5815         GSList *children;
5816         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5817 } ResTreeNode;
5818
5819 static int
5820 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5821 {
5822         ResTreeNode *t1 = (ResTreeNode*)a;
5823         ResTreeNode *t2 = (ResTreeNode*)b;
5824
5825         return t1->id - t2->id;
5826 }
5827
5828 /*
5829  * resource_tree_create:
5830  *
5831  *  Organize the resources into a resource tree.
5832  */
5833 static ResTreeNode *
5834 resource_tree_create (MonoArray *win32_resources)
5835 {
5836         ResTreeNode *tree, *res_node, *type_node, *lang_node;
5837         GSList *l;
5838         int i;
5839
5840         tree = g_new0 (ResTreeNode, 1);
5841         
5842         for (i = 0; i < mono_array_length (win32_resources); ++i) {
5843                 MonoReflectionWin32Resource *win32_res =
5844                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5845
5846                 /* Create node */
5847
5848                 /* FIXME: BUG: this stores managed references in unmanaged memory */
5849                 lang_node = g_new0 (ResTreeNode, 1);
5850                 lang_node->id = win32_res->lang_id;
5851                 lang_node->win32_res = win32_res;
5852
5853                 /* Create type node if neccesary */
5854                 type_node = NULL;
5855                 for (l = tree->children; l; l = l->next)
5856                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5857                                 type_node = (ResTreeNode*)l->data;
5858                                 break;
5859                         }
5860
5861                 if (!type_node) {
5862                         type_node = g_new0 (ResTreeNode, 1);
5863                         type_node->id = win32_res->res_type;
5864
5865                         /* 
5866                          * The resource types have to be sorted otherwise
5867                          * Windows Explorer can't display the version information.
5868                          */
5869                         tree->children = g_slist_insert_sorted (tree->children, 
5870                                 type_node, resource_tree_compare_by_id);
5871                 }
5872
5873                 /* Create res node if neccesary */
5874                 res_node = NULL;
5875                 for (l = type_node->children; l; l = l->next)
5876                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5877                                 res_node = (ResTreeNode*)l->data;
5878                                 break;
5879                         }
5880
5881                 if (!res_node) {
5882                         res_node = g_new0 (ResTreeNode, 1);
5883                         res_node->id = win32_res->res_id;
5884                         type_node->children = g_slist_append (type_node->children, res_node);
5885                 }
5886
5887                 res_node->children = g_slist_append (res_node->children, lang_node);
5888         }
5889
5890         return tree;
5891 }
5892
5893 /*
5894  * resource_tree_encode:
5895  * 
5896  *   Encode the resource tree into the format used in the PE file.
5897  */
5898 static void
5899 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5900 {
5901         char *entries;
5902         MonoPEResourceDir dir;
5903         MonoPEResourceDirEntry dir_entry;
5904         MonoPEResourceDataEntry data_entry;
5905         GSList *l;
5906         guint32 res_id_entries;
5907
5908         /*
5909          * For the format of the resource directory, see the article
5910          * "An In-Depth Look into the Win32 Portable Executable File Format" by
5911          * Matt Pietrek
5912          */
5913
5914         memset (&dir, 0, sizeof (dir));
5915         memset (&dir_entry, 0, sizeof (dir_entry));
5916         memset (&data_entry, 0, sizeof (data_entry));
5917
5918         g_assert (sizeof (dir) == 16);
5919         g_assert (sizeof (dir_entry) == 8);
5920         g_assert (sizeof (data_entry) == 16);
5921
5922         node->offset = p - begin;
5923
5924         /* IMAGE_RESOURCE_DIRECTORY */
5925         res_id_entries = g_slist_length (node->children);
5926         dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5927
5928         memcpy (p, &dir, sizeof (dir));
5929         p += sizeof (dir);
5930
5931         /* Reserve space for entries */
5932         entries = p;
5933         p += sizeof (dir_entry) * res_id_entries;
5934
5935         /* Write children */
5936         for (l = node->children; l; l = l->next) {
5937                 ResTreeNode *child = (ResTreeNode*)l->data;
5938
5939                 if (child->win32_res) {
5940                         guint32 size;
5941
5942                         child->offset = p - begin;
5943
5944                         /* IMAGE_RESOURCE_DATA_ENTRY */
5945                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5946                         size = mono_array_length (child->win32_res->res_data);
5947                         data_entry.rde_size = GUINT32_TO_LE (size);
5948
5949                         memcpy (p, &data_entry, sizeof (data_entry));
5950                         p += sizeof (data_entry);
5951
5952                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5953                         p += size;
5954                 } else {
5955                         resource_tree_encode (child, begin, p, &p);
5956                 }
5957         }
5958
5959         /* IMAGE_RESOURCE_ENTRY */
5960         for (l = node->children; l; l = l->next) {
5961                 ResTreeNode *child = (ResTreeNode*)l->data;
5962
5963                 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5964                 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5965
5966                 memcpy (entries, &dir_entry, sizeof (dir_entry));
5967                 entries += sizeof (dir_entry);
5968         }
5969
5970         *endbuf = p;
5971 }
5972
5973 static void
5974 resource_tree_free (ResTreeNode * node)
5975 {
5976         GSList * list;
5977         for (list = node->children; list; list = list->next)
5978                 resource_tree_free ((ResTreeNode*)list->data);
5979         g_slist_free(node->children);
5980         g_free (node);
5981 }
5982
5983 static void
5984 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5985 {
5986         char *buf;
5987         char *p;
5988         guint32 size, i;
5989         MonoReflectionWin32Resource *win32_res;
5990         ResTreeNode *tree;
5991
5992         if (!assemblyb->win32_resources)
5993                 return;
5994
5995         /*
5996          * Resources are stored in a three level tree inside the PE file.
5997          * - level one contains a node for each type of resource
5998          * - level two contains a node for each resource
5999          * - level three contains a node for each instance of a resource for a
6000          *   specific language.
6001          */
6002
6003         tree = resource_tree_create (assemblyb->win32_resources);
6004
6005         /* Estimate the size of the encoded tree */
6006         size = 0;
6007         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
6008                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
6009                 size += mono_array_length (win32_res->res_data);
6010         }
6011         /* Directory structure */
6012         size += mono_array_length (assemblyb->win32_resources) * 256;
6013         p = buf = (char *)g_malloc (size);
6014
6015         resource_tree_encode (tree, p, p, &p);
6016
6017         g_assert (p - buf <= size);
6018
6019         assembly->win32_res = (char *)g_malloc (p - buf);
6020         assembly->win32_res_size = p - buf;
6021         memcpy (assembly->win32_res, buf, p - buf);
6022
6023         g_free (buf);
6024         resource_tree_free (tree);
6025 }
6026
6027 static void
6028 fixup_resource_directory (char *res_section, char *p, guint32 rva)
6029 {
6030         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
6031         int i;
6032
6033         p += sizeof (MonoPEResourceDir);
6034         for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
6035                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
6036                 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
6037                 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
6038                         fixup_resource_directory (res_section, child, rva);
6039                 } else {
6040                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
6041                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
6042                 }
6043
6044                 p += sizeof (MonoPEResourceDirEntry);
6045         }
6046 }
6047
6048 static void
6049 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
6050 {
6051         guint32 dummy;
6052         if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
6053                 g_error ("WriteFile returned %d\n", GetLastError ());
6054 }
6055
6056 /*
6057  * mono_image_create_pefile:
6058  * @mb: a module builder object
6059  * 
6060  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
6061  * assembly->pefile where it can be easily retrieved later in chunks.
6062  */
6063 gboolean
6064 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6065 {
6066         MonoMSDOSHeader *msdos;
6067         MonoDotNetHeader *header;
6068         MonoSectionTable *section;
6069         MonoCLIHeader *cli_header;
6070         guint32 size, image_size, virtual_base, text_offset;
6071         guint32 header_start, section_start, file_offset, virtual_offset;
6072         MonoDynamicImage *assembly;
6073         MonoReflectionAssemblyBuilder *assemblyb;
6074         MonoDynamicStream pefile_stream = {0};
6075         MonoDynamicStream *pefile = &pefile_stream;
6076         int i, nsections;
6077         guint32 *rva, value;
6078         guchar *p;
6079         static const unsigned char msheader[] = {
6080                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
6081                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6082                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
6083                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
6084                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
6085                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
6086                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
6087                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6088         };
6089
6090         mono_error_init (error);
6091
6092         assemblyb = mb->assemblyb;
6093
6094         mono_image_basic_init (assemblyb);
6095         assembly = mb->dynamic_image;
6096
6097         assembly->pe_kind = assemblyb->pe_kind;
6098         assembly->machine = assemblyb->machine;
6099         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
6100         ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
6101         
6102         if (!mono_image_build_metadata (mb, error))
6103                 return FALSE;
6104         
6105
6106         if (mb->is_main && assemblyb->resources) {
6107                 int len = mono_array_length (assemblyb->resources);
6108                 for (i = 0; i < len; ++i)
6109                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
6110         }
6111
6112         if (mb->resources) {
6113                 int len = mono_array_length (mb->resources);
6114                 for (i = 0; i < len; ++i)
6115                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
6116         }
6117
6118         if (!build_compressed_metadata (assembly, error))
6119                 return FALSE;
6120
6121         if (mb->is_main)
6122                 assembly_add_win32_resources (assembly, assemblyb);
6123
6124         nsections = calc_section_size (assembly);
6125         
6126         /* The DOS header and stub */
6127         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
6128         mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
6129
6130         /* the dotnet header */
6131         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
6132
6133         /* the section tables */
6134         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
6135
6136         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
6137         virtual_offset = VIRT_ALIGN;
6138         image_size = 0;
6139
6140         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6141                 if (!assembly->sections [i].size)
6142                         continue;
6143                 /* align offsets */
6144                 file_offset += FILE_ALIGN - 1;
6145                 file_offset &= ~(FILE_ALIGN - 1);
6146                 virtual_offset += VIRT_ALIGN - 1;
6147                 virtual_offset &= ~(VIRT_ALIGN - 1);
6148
6149                 assembly->sections [i].offset = file_offset;
6150                 assembly->sections [i].rva = virtual_offset;
6151
6152                 file_offset += assembly->sections [i].size;
6153                 virtual_offset += assembly->sections [i].size;
6154                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
6155         }
6156
6157         file_offset += FILE_ALIGN - 1;
6158         file_offset &= ~(FILE_ALIGN - 1);
6159
6160         image_size += section_start + sizeof (MonoSectionTable) * nsections;
6161
6162         /* back-patch info */
6163         msdos = (MonoMSDOSHeader*)pefile->data;
6164         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
6165
6166         header = (MonoDotNetHeader*)(pefile->data + header_start);
6167         header->pesig [0] = 'P';
6168         header->pesig [1] = 'E';
6169         
6170         header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
6171         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
6172         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
6173         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
6174         if (assemblyb->pekind == 1) {
6175                 /* it's a dll */
6176                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
6177         } else {
6178                 /* it's an exe */
6179                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
6180         }
6181
6182         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
6183
6184         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
6185         header->pe.pe_major = 6;
6186         header->pe.pe_minor = 0;
6187         size = assembly->sections [MONO_SECTION_TEXT].size;
6188         size += FILE_ALIGN - 1;
6189         size &= ~(FILE_ALIGN - 1);
6190         header->pe.pe_code_size = GUINT32_FROM_LE(size);
6191         size = assembly->sections [MONO_SECTION_RSRC].size;
6192         size += FILE_ALIGN - 1;
6193         size &= ~(FILE_ALIGN - 1);
6194         header->pe.pe_data_size = GUINT32_FROM_LE(size);
6195         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
6196         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6197         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6198         /* pe_rva_entry_point always at the beginning of the text section */
6199         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
6200
6201         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
6202         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
6203         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
6204         header->nt.pe_os_major = GUINT16_FROM_LE (4);
6205         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
6206         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
6207         size = section_start;
6208         size += FILE_ALIGN - 1;
6209         size &= ~(FILE_ALIGN - 1);
6210         header->nt.pe_header_size = GUINT32_FROM_LE (size);
6211         size = image_size;
6212         size += VIRT_ALIGN - 1;
6213         size &= ~(VIRT_ALIGN - 1);
6214         header->nt.pe_image_size = GUINT32_FROM_LE (size);
6215
6216         /*
6217         // Translate the PEFileKind value to the value expected by the Windows loader
6218         */
6219         {
6220                 short kind;
6221
6222                 /*
6223                 // PEFileKinds.Dll == 1
6224                 // PEFileKinds.ConsoleApplication == 2
6225                 // PEFileKinds.WindowApplication == 3
6226                 //
6227                 // need to get:
6228                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
6229                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
6230                 */
6231                 if (assemblyb->pekind == 3)
6232                         kind = 2;
6233                 else
6234                         kind = 3;
6235                 
6236                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
6237         }    
6238         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
6239         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
6240         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
6241         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
6242         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
6243         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
6244
6245         /* fill data directory entries */
6246
6247         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
6248         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
6249
6250         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
6251         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
6252
6253         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
6254         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
6255         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
6256         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6257         /* patch entrypoint name */
6258         if (assemblyb->pekind == 1)
6259                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
6260         else
6261                 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
6262         /* patch imported function RVA name */
6263         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
6264         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
6265
6266         /* the import table */
6267         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
6268         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
6269         /* patch imported dll RVA name and other entries in the dir */
6270         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
6271         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
6272         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
6273         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
6274         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
6275         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
6276
6277         p = (guchar*)(assembly->code.data + assembly->ilt_offset);
6278         value = (assembly->text_rva + assembly->imp_names_offset);
6279         *p++ = (value) & 0xff;
6280         *p++ = (value >> 8) & (0xff);
6281         *p++ = (value >> 16) & (0xff);
6282         *p++ = (value >> 24) & (0xff);
6283
6284         /* the CLI header info */
6285         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
6286         cli_header->ch_size = GUINT32_FROM_LE (72);
6287         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
6288         cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
6289         cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
6290         if (assemblyb->entry_point) {
6291                 guint32 table_idx = 0;
6292                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
6293                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
6294                         table_idx = methodb->table_idx;
6295                 } else {
6296                         table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
6297                 }
6298                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
6299         } else {
6300                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
6301         }
6302         /* The embedded managed resources */
6303         text_offset = assembly->text_rva + assembly->code.index;
6304         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
6305         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
6306         text_offset += assembly->resources.index;
6307         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
6308         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
6309         text_offset += assembly->meta_size;
6310         if (assembly->strong_name_size) {
6311                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
6312                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
6313                 text_offset += assembly->strong_name_size;
6314         }
6315
6316         /* write the section tables and section content */
6317         section = (MonoSectionTable*)(pefile->data + section_start);
6318         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6319                 static const char section_names [][7] = {
6320                         ".text", ".rsrc", ".reloc"
6321                 };
6322                 if (!assembly->sections [i].size)
6323                         continue;
6324                 strcpy (section->st_name, section_names [i]);
6325                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
6326                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
6327                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
6328                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
6329                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
6330                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
6331                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
6332                 section ++;
6333         }
6334         
6335         checked_write_file (file, pefile->data, pefile->index);
6336         
6337         mono_dynamic_stream_reset (pefile);
6338         
6339         for (i = 0; i < MONO_SECTION_MAX; ++i) {
6340                 if (!assembly->sections [i].size)
6341                         continue;
6342                 
6343                 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6344                         g_error ("SetFilePointer returned %d\n", GetLastError ());
6345                 
6346                 switch (i) {
6347                 case MONO_SECTION_TEXT:
6348                         /* patch entry point */
6349                         p = (guchar*)(assembly->code.data + 2);
6350                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
6351                         *p++ = (value) & 0xff;
6352                         *p++ = (value >> 8) & 0xff;
6353                         *p++ = (value >> 16) & 0xff;
6354                         *p++ = (value >> 24) & 0xff;
6355                 
6356                         checked_write_file (file, assembly->code.data, assembly->code.index);
6357                         checked_write_file (file, assembly->resources.data, assembly->resources.index);
6358                         checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
6359                         checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
6360                                 
6361
6362                         g_free (assembly->image.raw_metadata);
6363                         break;
6364                 case MONO_SECTION_RELOC: {
6365                         struct {
6366                                 guint32 page_rva;
6367                                 guint32 block_size;
6368                                 guint16 type_and_offset;
6369                                 guint16 term;
6370                         } reloc;
6371                         
6372                         g_assert (sizeof (reloc) == 12);
6373                         
6374                         reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
6375                         reloc.block_size = GUINT32_FROM_LE (12);
6376                         
6377                         /* 
6378                          * the entrypoint is always at the start of the text section 
6379                          * 3 is IMAGE_REL_BASED_HIGHLOW
6380                          * 2 is patch_size_rva - text_rva
6381                          */
6382                         reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
6383                         reloc.term = 0;
6384                         
6385                         checked_write_file (file, &reloc, sizeof (reloc));
6386                         
6387                         break;
6388                 }
6389                 case MONO_SECTION_RSRC:
6390                         if (assembly->win32_res) {
6391
6392                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
6393                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
6394                                 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
6395                         }
6396                         break;
6397                 default:
6398                         g_assert_not_reached ();
6399                 }
6400         }
6401         
6402         /* check that the file is properly padded */
6403         if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
6404                 g_error ("SetFilePointer returned %d\n", GetLastError ());
6405         if (! SetEndOfFile (file))
6406                 g_error ("SetEndOfFile returned %d\n", GetLastError ());
6407         
6408         mono_dynamic_stream_reset (&assembly->code);
6409         mono_dynamic_stream_reset (&assembly->us);
6410         mono_dynamic_stream_reset (&assembly->blob);
6411         mono_dynamic_stream_reset (&assembly->guid);
6412         mono_dynamic_stream_reset (&assembly->sheap);
6413
6414         g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
6415         g_hash_table_destroy (assembly->blob_cache);
6416         assembly->blob_cache = NULL;
6417
6418         return TRUE;
6419 }
6420
6421 #else /* DISABLE_REFLECTION_EMIT_SAVE */
6422
6423 gboolean
6424 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file, MonoError *error)
6425 {
6426         g_assert_not_reached ();
6427 }
6428
6429 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
6430
6431 #ifndef DISABLE_REFLECTION_EMIT
6432
6433 MonoReflectionModule *
6434 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
6435 {
6436         MonoError error;
6437         MonoReflectionModule *result = NULL;
6438         char *name;
6439         MonoImage *image;
6440         MonoImageOpenStatus status;
6441         MonoDynamicAssembly *assembly;
6442         guint32 module_count;
6443         MonoImage **new_modules;
6444         gboolean *new_modules_loaded;
6445         
6446         name = mono_string_to_utf8 (fileName);
6447
6448         image = mono_image_open (name, &status);
6449         if (!image) {
6450                 MonoException *exc;
6451                 if (status == MONO_IMAGE_ERROR_ERRNO)
6452                         exc = mono_get_exception_file_not_found (fileName);
6453                 else
6454                         exc = mono_get_exception_bad_image_format (name);
6455                 g_free (name);
6456                 mono_raise_exception (exc);
6457         }
6458
6459         g_free (name);
6460
6461         assembly = ab->dynamic_assembly;
6462         image->assembly = (MonoAssembly*)assembly;
6463
6464         module_count = image->assembly->image->module_count;
6465         new_modules = g_new0 (MonoImage *, module_count + 1);
6466         new_modules_loaded = g_new0 (gboolean, module_count + 1);
6467
6468         if (image->assembly->image->modules)
6469                 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
6470         if (image->assembly->image->modules_loaded)
6471                 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
6472         new_modules [module_count] = image;
6473         new_modules_loaded [module_count] = TRUE;
6474         mono_image_addref (image);
6475
6476         g_free (image->assembly->image->modules);
6477         image->assembly->image->modules = new_modules;
6478         image->assembly->image->modules_loaded = new_modules_loaded;
6479         image->assembly->image->module_count ++;
6480
6481         mono_assembly_load_references (image, &status);
6482         if (status) {
6483                 mono_image_close (image);
6484                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6485         }
6486
6487         result = mono_module_get_object_checked (mono_domain_get (), image, &error);
6488         mono_error_raise_exception (&error); /* FIXME don't raise here */
6489         return result;
6490 }
6491
6492 #endif /* DISABLE_REFLECTION_EMIT */
6493
6494 /*
6495  * We need to return always the same object for MethodInfo, FieldInfo etc..
6496  * but we need to consider the reflected type.
6497  * type uses a different hash, since it uses custom hash/equal functions.
6498  */
6499
6500 typedef struct {
6501         gpointer item;
6502         MonoClass *refclass;
6503 } ReflectedEntry;
6504
6505 static gboolean
6506 reflected_equal (gconstpointer a, gconstpointer b) {
6507         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6508         const ReflectedEntry *eb = (const ReflectedEntry *)b;
6509
6510         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6511 }
6512
6513 static guint
6514 reflected_hash (gconstpointer a) {
6515         const ReflectedEntry *ea = (const ReflectedEntry *)a;
6516         return mono_aligned_addr_hash (ea->item);
6517 }
6518
6519 #define CHECK_OBJECT(t,p,k)     \
6520         do {    \
6521                 t _obj; \
6522                 ReflectedEntry e;       \
6523                 e.item = (p);   \
6524                 e.refclass = (k);       \
6525                 mono_domain_lock (domain);      \
6526                 if (!domain->refobject_hash)    \
6527                         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");  \
6528                 if ((_obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &e))) {        \
6529                         mono_domain_unlock (domain);    \
6530                         return _obj;    \
6531                 }       \
6532         mono_domain_unlock (domain); \
6533         } while (0)
6534
6535 #ifdef HAVE_BOEHM_GC
6536 /* ReflectedEntry doesn't need to be GC tracked */
6537 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6538 #define FREE_REFENTRY(entry) g_free ((entry))
6539 #define REFENTRY_REQUIRES_CLEANUP
6540 #else
6541 #define ALLOC_REFENTRY (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6542 /* FIXME: */
6543 #define FREE_REFENTRY(entry)
6544 #endif
6545
6546 #define CACHE_OBJECT(t,p,o,k)   \
6547         do {    \
6548                 t _obj; \
6549         ReflectedEntry pe; \
6550         pe.item = (p); \
6551         pe.refclass = (k); \
6552         mono_domain_lock (domain); \
6553                 if (!domain->refobject_hash)    \
6554                         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");  \
6555         _obj = (t)mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6556         if (!_obj) { \
6557                     ReflectedEntry *e = ALLOC_REFENTRY;         \
6558                     e->item = (p);      \
6559                     e->refclass = (k);  \
6560                     mono_g_hash_table_insert (domain->refobject_hash, e,o);     \
6561             _obj = o; \
6562         } \
6563                 mono_domain_unlock (domain);    \
6564         return _obj; \
6565         } while (0)
6566
6567 static void
6568 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6569 {
6570         mono_domain_lock (domain);
6571         if (domain->refobject_hash) {
6572         ReflectedEntry pe;
6573                 gpointer orig_pe, orig_value;
6574
6575                 pe.item = o;
6576                 pe.refclass = klass;
6577                 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6578                         mono_g_hash_table_remove (domain->refobject_hash, &pe);
6579                         FREE_REFENTRY (orig_pe);
6580                 }
6581         }
6582         mono_domain_unlock (domain);
6583 }
6584
6585 #ifdef REFENTRY_REQUIRES_CLEANUP
6586 static void
6587 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6588 {
6589         FREE_REFENTRY (key);
6590 }
6591 #endif
6592
6593 void
6594 mono_reflection_cleanup_domain (MonoDomain *domain)
6595 {
6596         if (domain->refobject_hash) {
6597 /*let's avoid scanning the whole hashtable if not needed*/
6598 #ifdef REFENTRY_REQUIRES_CLEANUP
6599                 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6600 #endif
6601                 mono_g_hash_table_destroy (domain->refobject_hash);
6602                 domain->refobject_hash = NULL;
6603         }
6604 }
6605
6606 #ifndef DISABLE_REFLECTION_EMIT
6607 static gpointer
6608 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6609 {
6610         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6611 }
6612
6613 static gpointer
6614 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6615 {
6616         CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6617 }
6618
6619 void
6620 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6621 {
6622         MonoDynamicImage *image = moduleb->dynamic_image;
6623         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6624         if (!image) {
6625                 MonoError error;
6626                 int module_count;
6627                 MonoImage **new_modules;
6628                 MonoImage *ass;
6629                 char *name, *fqname;
6630                 /*
6631                  * FIXME: we already created an image in mono_image_basic_init (), but
6632                  * we don't know which module it belongs to, since that is only 
6633                  * determined at assembly save time.
6634                  */
6635                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6636                 name = mono_string_to_utf8 (ab->name);
6637                 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6638                 if (!mono_error_ok (&error)) {
6639                         g_free (name);
6640                         mono_error_raise_exception (&error);
6641                 }
6642                 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6643
6644                 moduleb->module.image = &image->image;
6645                 moduleb->dynamic_image = image;
6646                 register_module (mono_object_domain (moduleb), moduleb, image);
6647
6648                 /* register the module with the assembly */
6649                 ass = ab->dynamic_assembly->assembly.image;
6650                 module_count = ass->module_count;
6651                 new_modules = g_new0 (MonoImage *, module_count + 1);
6652
6653                 if (ass->modules)
6654                         memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6655                 new_modules [module_count] = &image->image;
6656                 mono_image_addref (&image->image);
6657
6658                 g_free (ass->modules);
6659                 ass->modules = new_modules;
6660                 ass->module_count ++;
6661         }
6662 }
6663
6664 void
6665 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6666 {
6667         MonoDynamicImage *image = moduleb->dynamic_image;
6668
6669         g_assert (type->type);
6670         image->wrappers_type = mono_class_from_mono_type (type->type);
6671 }
6672
6673 #endif
6674
6675 /*
6676  * mono_assembly_get_object:
6677  * @domain: an app domain
6678  * @assembly: an assembly
6679  *
6680  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6681  */
6682 MonoReflectionAssembly*
6683 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6684 {
6685         MonoError error;
6686         MonoReflectionAssembly *result;
6687         result = mono_assembly_get_object_checked (domain, assembly, &error);
6688         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6689         return result;
6690 }
6691 /*
6692  * mono_assembly_get_object_checked:
6693  * @domain: an app domain
6694  * @assembly: an assembly
6695  *
6696  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6697  */
6698 MonoReflectionAssembly*
6699 mono_assembly_get_object_checked (MonoDomain *domain, MonoAssembly *assembly, MonoError *error)
6700 {
6701         MonoReflectionAssembly *res;
6702         
6703         mono_error_init (error);
6704
6705         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6706         res = (MonoReflectionAssembly *)mono_object_new_checked (domain, mono_class_get_mono_assembly_class (), error);
6707         if (!res)
6708                 return NULL;
6709         res->assembly = assembly;
6710
6711         CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6712 }
6713
6714
6715
6716 MonoReflectionModule*   
6717 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
6718 {
6719         MonoError error;
6720         MonoReflectionModule *result;
6721         result = mono_module_get_object_checked (domain, image, &error);
6722         mono_error_raise_exception (&error);
6723         return result;
6724 }
6725
6726 MonoReflectionModule*
6727 mono_module_get_object_checked (MonoDomain *domain, MonoImage *image, MonoError *error)
6728 {
6729         MonoReflectionModule *res;
6730         char* basename;
6731         
6732         mono_error_init (error);
6733         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6734         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6735         if (!res)
6736                 return NULL;
6737
6738         res->image = image;
6739         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6740         if (!assm_obj)
6741                 return NULL;
6742         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6743
6744         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6745         basename = g_path_get_basename (image->name);
6746         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6747         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6748         
6749         g_free (basename);
6750
6751         if (image->assembly->image == image) {
6752                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6753         } else {
6754                 int i;
6755                 res->token = 0;
6756                 if (image->assembly->image->modules) {
6757                         for (i = 0; i < image->assembly->image->module_count; i++) {
6758                                 if (image->assembly->image->modules [i] == image)
6759                                         res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6760                         }
6761                         g_assert (res->token);
6762                 }
6763         }
6764
6765         CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6766 }
6767
6768 MonoReflectionModule*
6769 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6770 {
6771         MonoError error;
6772         MonoReflectionModule *result;
6773         result = mono_module_file_get_object_checked (domain, image, table_index, &error);
6774         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
6775         return result;
6776 }
6777
6778 MonoReflectionModule*
6779 mono_module_file_get_object_checked (MonoDomain *domain, MonoImage *image, int table_index, MonoError *error)
6780 {
6781         MonoReflectionModule *res;
6782         MonoTableInfo *table;
6783         guint32 cols [MONO_FILE_SIZE];
6784         const char *name;
6785         guint32 i, name_idx;
6786         const char *val;
6787         
6788         mono_error_init (error);
6789
6790         res = (MonoReflectionModule *)mono_object_new_checked (domain, mono_class_get_mono_module_class (), error);
6791         if (!res)
6792                 return NULL;
6793
6794         table = &image->tables [MONO_TABLE_FILE];
6795         g_assert (table_index < table->rows);
6796         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6797
6798         res->image = NULL;
6799         MonoReflectionAssembly *assm_obj = mono_assembly_get_object_checked (domain, image->assembly, error);
6800         if (!assm_obj)
6801                 return NULL;
6802         MONO_OBJECT_SETREF (res, assembly, assm_obj);
6803         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6804
6805         /* Check whenever the row has a corresponding row in the moduleref table */
6806         table = &image->tables [MONO_TABLE_MODULEREF];
6807         for (i = 0; i < table->rows; ++i) {
6808                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6809                 val = mono_metadata_string_heap (image, name_idx);
6810                 if (strcmp (val, name) == 0)
6811                         res->image = image->modules [i];
6812         }
6813
6814         MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6815         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6816         MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6817         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6818         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6819
6820         return res;
6821 }
6822
6823 static gboolean
6824 verify_safe_for_managed_space (MonoType *type)
6825 {
6826         switch (type->type) {
6827 #ifdef DEBUG_HARDER
6828         case MONO_TYPE_ARRAY:
6829                 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6830         case MONO_TYPE_PTR:
6831                 return verify_safe_for_managed_space (type->data.type);
6832         case MONO_TYPE_SZARRAY:
6833                 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6834         case MONO_TYPE_GENERICINST: {
6835                 MonoGenericInst *inst = type->data.generic_class->inst;
6836                 int i;
6837                 if (!inst->is_open)
6838                         break;
6839                 for (i = 0; i < inst->type_argc; ++i)
6840                         if (!verify_safe_for_managed_space (inst->type_argv [i]))
6841                                 return FALSE;
6842                 return TRUE;
6843         }
6844 #endif
6845         case MONO_TYPE_VAR:
6846         case MONO_TYPE_MVAR:
6847                 return TRUE;
6848         default:
6849                 return TRUE;
6850         }
6851 }
6852
6853 static MonoType*
6854 mono_type_normalize (MonoType *type)
6855 {
6856         int i;
6857         MonoGenericClass *gclass;
6858         MonoGenericInst *ginst;
6859         MonoClass *gtd;
6860         MonoGenericContainer *gcontainer;
6861         MonoType **argv = NULL;
6862         gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6863
6864         if (type->type != MONO_TYPE_GENERICINST)
6865                 return type;
6866
6867         gclass = type->data.generic_class;
6868         ginst = gclass->context.class_inst;
6869         if (!ginst->is_open)
6870                 return type;
6871
6872         gtd = gclass->container_class;
6873         gcontainer = gtd->generic_container;
6874         argv = g_newa (MonoType*, ginst->type_argc);
6875
6876         for (i = 0; i < ginst->type_argc; ++i) {
6877                 MonoType *t = ginst->type_argv [i], *norm;
6878                 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6879                         is_denorm_gtd = FALSE;
6880                 norm = mono_type_normalize (t);
6881                 argv [i] = norm;
6882                 if (norm != t)
6883                         requires_rebind = TRUE;
6884         }
6885
6886         if (is_denorm_gtd)
6887                 return type->byref == gtd->byval_arg.byref ? &gtd->byval_arg : &gtd->this_arg;
6888
6889         if (requires_rebind) {
6890                 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6891                 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6892         }
6893
6894         return type;
6895 }
6896 /*
6897  * mono_type_get_object:
6898  * @domain: an app domain
6899  * @type: a type
6900  *
6901  * Return an System.MonoType object representing the type @type.
6902  */
6903 MonoReflectionType*
6904 mono_type_get_object (MonoDomain *domain, MonoType *type)
6905 {
6906         MonoError error;
6907         MonoReflectionType *ret = mono_type_get_object_checked (domain, type, &error);
6908         mono_error_raise_exception (&error);
6909
6910         return ret;
6911 }
6912
6913 MonoReflectionType*
6914 mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *error)
6915 {
6916         MonoType *norm_type;
6917         MonoReflectionType *res;
6918         MonoClass *klass;
6919
6920         mono_error_init (error);
6921
6922         klass = mono_class_from_mono_type (type);
6923
6924         /*we must avoid using @type as it might have come
6925          * from a mono_metadata_type_dup and the caller
6926          * expects that is can be freed.
6927          * Using the right type from 
6928          */
6929         type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6930
6931         /* void is very common */
6932         if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6933                 return (MonoReflectionType*)domain->typeof_void;
6934
6935         /*
6936          * If the vtable of the given class was already created, we can use
6937          * the MonoType from there and avoid all locking and hash table lookups.
6938          * 
6939          * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6940          * that the resulting object is different.   
6941          */
6942         if (type == &klass->byval_arg && !image_is_dynamic (klass->image)) {
6943                 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6944                 if (vtable && vtable->type)
6945                         return (MonoReflectionType *)vtable->type;
6946         }
6947
6948         mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6949         mono_domain_lock (domain);
6950         if (!domain->type_hash)
6951                 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
6952                                 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
6953         if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) {
6954                 mono_domain_unlock (domain);
6955                 mono_loader_unlock ();
6956                 return res;
6957         }
6958
6959         /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6960          * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6961          * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6962          * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6963          * artifact of how generics are encoded and should be transparent to managed code so we
6964          * need to weed out this diference when retrieving managed System.Type objects.
6965          */
6966         norm_type = mono_type_normalize (type);
6967         if (norm_type != type) {
6968                 res = mono_type_get_object_checked (domain, norm_type, error);
6969                 if (!mono_error_ok (error))
6970                         return NULL;
6971                 mono_g_hash_table_insert (domain->type_hash, type, res);
6972                 mono_domain_unlock (domain);
6973                 mono_loader_unlock ();
6974                 return res;
6975         }
6976
6977         /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6978         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6979                 g_assert (0);
6980
6981         if (!verify_safe_for_managed_space (type)) {
6982                 mono_domain_unlock (domain);
6983                 mono_loader_unlock ();
6984                 mono_error_set_generic_error (error, "System", "InvalidOperationException", "This type cannot be propagated to managed space");
6985                 return NULL;
6986         }
6987
6988         if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6989                 gboolean is_type_done = TRUE;
6990                 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6991                  * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6992                  * We can't simply close the types as this will interfere with other parts of the generics machinery.
6993                 */
6994                 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6995                         MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6996
6997                         if (gparam->owner && gparam->owner->is_method) {
6998                                 MonoMethod *method = gparam->owner->owner.method;
6999                                 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
7000                                         is_type_done = FALSE;
7001                         } else if (gparam->owner && !gparam->owner->is_method) {
7002                                 MonoClass *klass = gparam->owner->owner.klass;
7003                                 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
7004                                         is_type_done = FALSE;
7005                         }
7006                 } 
7007
7008                 /* g_assert_not_reached (); */
7009                 /* should this be considered an error condition? */
7010                 if (is_type_done && !type->byref) {
7011                         mono_domain_unlock (domain);
7012                         mono_loader_unlock ();
7013                         return (MonoReflectionType *)mono_class_get_ref_info (klass);
7014                 }
7015         }
7016         /* This is stored in vtables/JITted code so it has to be pinned */
7017         res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class, error);
7018         if (!mono_error_ok (error))
7019                 return NULL;
7020
7021         res->type = type;
7022         mono_g_hash_table_insert (domain->type_hash, type, res);
7023
7024         if (type->type == MONO_TYPE_VOID)
7025                 domain->typeof_void = (MonoObject*)res;
7026
7027         mono_domain_unlock (domain);
7028         mono_loader_unlock ();
7029         return res;
7030 }
7031
7032 /*
7033  * mono_method_get_object:
7034  * @domain: an app domain
7035  * @method: a method
7036  * @refclass: the reflected type (can be NULL)
7037  *
7038  * Return an System.Reflection.MonoMethod object representing the method @method.
7039  */
7040 MonoReflectionMethod*
7041 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7042 {
7043         MonoError error;
7044         MonoReflectionMethod *ret = NULL;
7045         ret = mono_method_get_object_checked (domain, method, refclass, &error);
7046         mono_error_raise_exception (&error);
7047         return ret;
7048 }
7049
7050 /*
7051  * mono_method_get_object_checked:
7052  * @domain: an app domain
7053  * @method: a method
7054  * @refclass: the reflected type (can be NULL)
7055  * @error: set on error.
7056  *
7057  * Return an System.Reflection.MonoMethod object representing the method @method.
7058  * Returns NULL and sets @error on error.
7059  */
7060 MonoReflectionMethod*
7061 mono_method_get_object_checked (MonoDomain *domain, MonoMethod *method, MonoClass *refclass, MonoError *error)
7062 {
7063         /*
7064          * We use the same C representation for methods and constructors, but the type 
7065          * name in C# is different.
7066          */
7067         MonoReflectionType *rt;
7068         MonoClass *klass;
7069         MonoReflectionMethod *ret;
7070
7071         mono_error_init (error);
7072
7073         if (method->is_inflated) {
7074                 MonoReflectionGenericMethod *gret;
7075
7076                 if (!refclass)
7077                         refclass = method->klass;
7078                 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7079                 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
7080                         klass = mono_class_get_mono_generic_cmethod_class ();
7081                 } else {
7082                         klass = mono_class_get_mono_generic_method_class ();
7083                 }
7084                 gret = (MonoReflectionGenericMethod*)mono_object_new_checked (domain, klass, error);
7085                 if (!mono_error_ok (error))
7086                         goto leave;
7087                 gret->method.method = method;
7088
7089                 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
7090
7091                 rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7092                 if (!mono_error_ok (error))
7093                     goto leave;
7094
7095                 MONO_OBJECT_SETREF (gret, method.reftype, rt);
7096
7097                 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
7098         }
7099
7100         if (!refclass)
7101                 refclass = method->klass;
7102
7103         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
7104         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
7105                 klass = mono_class_get_mono_cmethod_class ();
7106         }
7107         else {
7108                 klass = mono_class_get_mono_method_class ();
7109         }
7110         ret = (MonoReflectionMethod*)mono_object_new_checked (domain, klass, error);
7111         if (!mono_error_ok (error))
7112                 goto leave;
7113         ret->method = method;
7114
7115         rt = mono_type_get_object_checked (domain, &refclass->byval_arg, error);
7116         if (!mono_error_ok (error))
7117                 goto leave;
7118
7119         MONO_OBJECT_SETREF (ret, reftype, rt);
7120
7121         CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
7122
7123 leave:
7124         g_assert (!mono_error_ok (error));
7125         return NULL;
7126 }
7127
7128 /*
7129  * mono_method_clear_object:
7130  *
7131  *   Clear the cached reflection objects for the dynamic method METHOD.
7132  */
7133 void
7134 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
7135 {
7136         MonoClass *klass;
7137         g_assert (method_is_dynamic (method));
7138
7139         klass = method->klass;
7140         while (klass) {
7141                 clear_cached_object (domain, method, klass);
7142                 klass = klass->parent;
7143         }
7144         /* Added by mono_param_get_objects () */
7145         clear_cached_object (domain, &(method->signature), NULL);
7146         klass = method->klass;
7147         while (klass) {
7148                 clear_cached_object (domain, &(method->signature), klass);
7149                 klass = klass->parent;
7150         }
7151 }
7152
7153 /*
7154  * mono_field_get_object:
7155  * @domain: an app domain
7156  * @klass: a type
7157  * @field: a field
7158  *
7159  * Return an System.Reflection.MonoField object representing the field @field
7160  * in class @klass.
7161  */
7162 MonoReflectionField*
7163 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
7164 {
7165         MonoError error;
7166         MonoReflectionField *result;
7167         result = mono_field_get_object_checked (domain, klass, field, &error);
7168         mono_error_raise_exception (&error);
7169         return result;
7170 }
7171
7172 /*
7173  * mono_field_get_object_checked:
7174  * @domain: an app domain
7175  * @klass: a type
7176  * @field: a field
7177  * @error: set on error
7178  *
7179  * Return an System.Reflection.MonoField object representing the field @field
7180  * in class @klass. On error, returns NULL and sets @error.
7181  */
7182 MonoReflectionField*
7183 mono_field_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoClassField *field, MonoError *error)
7184 {
7185         MonoReflectionType *rt;
7186         MonoReflectionField *res;
7187
7188         mono_error_init (error);
7189
7190         CHECK_OBJECT (MonoReflectionField *, field, klass);
7191         res = (MonoReflectionField *)mono_object_new_checked (domain, mono_class_get_mono_field_class (), error);
7192         if (!res)
7193                 return NULL;
7194         res->klass = klass;
7195         res->field = field;
7196         MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
7197
7198         if (is_field_on_inst (field)) {
7199                 res->attrs = get_field_on_inst_generic_type (field)->attrs;
7200
7201                 rt = mono_type_get_object_checked (domain, field->type, error);
7202                 if (!mono_error_ok (error))
7203                         return NULL;
7204
7205                 MONO_OBJECT_SETREF (res, type, rt);
7206         } else {
7207                 if (field->type) {
7208                         rt = mono_type_get_object_checked (domain, field->type, error);
7209                         if (!mono_error_ok (error))
7210                                 return NULL;
7211
7212                         MONO_OBJECT_SETREF (res, type, rt);
7213                 }
7214                 res->attrs = mono_field_get_flags (field);
7215         }
7216         CACHE_OBJECT (MonoReflectionField *, field, res, klass);
7217 }
7218
7219 /*
7220  * mono_property_get_object:
7221  * @domain: an app domain
7222  * @klass: a type
7223  * @property: a property
7224  *
7225  * Return an System.Reflection.MonoProperty object representing the property @property
7226  * in class @klass.
7227  */
7228 MonoReflectionProperty*
7229 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
7230 {
7231         MonoError error;
7232         MonoReflectionProperty *result;
7233         result = mono_property_get_object_checked (domain, klass, property, &error);
7234         mono_error_raise_exception (&error);
7235         return result;
7236 }
7237
7238 /**
7239  * mono_property_get_object:
7240  * @domain: an app domain
7241  * @klass: a type
7242  * @property: a property
7243  * @error: set on error
7244  *
7245  * Return an System.Reflection.MonoProperty object representing the property @property
7246  * in class @klass.  On error returns NULL and sets @error.
7247  */
7248 MonoReflectionProperty*
7249 mono_property_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoProperty *property, MonoError *error)
7250 {
7251         MonoReflectionProperty *res;
7252
7253         mono_error_init (error);
7254
7255         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
7256         res = (MonoReflectionProperty *)mono_object_new_checked (domain, mono_class_get_mono_property_class (), error);
7257         if (!res)
7258                 return NULL;
7259         res->klass = klass;
7260         res->property = property;
7261         CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
7262 }
7263
7264 /*
7265  * mono_event_get_object:
7266  * @domain: an app domain
7267  * @klass: a type
7268  * @event: a event
7269  *
7270  * Return an System.Reflection.MonoEvent object representing the event @event
7271  * in class @klass.
7272  */
7273 MonoReflectionEvent*
7274 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
7275 {
7276         MonoError error;
7277         MonoReflectionEvent *result;
7278         result = mono_event_get_object_checked (domain, klass, event, &error);
7279         mono_error_raise_exception (&error);
7280         return result;
7281 }
7282
7283 /**
7284  * mono_event_get_object_checked:
7285  * @domain: an app domain
7286  * @klass: a type
7287  * @event: a event
7288  * @error: set on error
7289  *
7290  * Return an System.Reflection.MonoEvent object representing the event @event
7291  * in class @klass. On failure sets @error and returns NULL
7292  */
7293 MonoReflectionEvent*
7294 mono_event_get_object_checked (MonoDomain *domain, MonoClass *klass, MonoEvent *event, MonoError *error)
7295 {
7296         MonoReflectionEvent *res;
7297         MonoReflectionMonoEvent *mono_event;
7298
7299         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
7300         mono_event = (MonoReflectionMonoEvent *)mono_object_new_checked (domain, mono_class_get_mono_event_class (), error);
7301         if (!mono_event)
7302                 return NULL;
7303         mono_event->klass = klass;
7304         mono_event->event = event;
7305         res = (MonoReflectionEvent*)mono_event;
7306         CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
7307 }
7308
7309 /**
7310  * mono_get_reflection_missing_object:
7311  * @domain: Domain where the object lives
7312  *
7313  * Returns the System.Reflection.Missing.Value singleton object
7314  * (of type System.Reflection.Missing).
7315  *
7316  * Used as the value for ParameterInfo.DefaultValue when Optional
7317  * is present
7318  */
7319 static MonoObject *
7320 mono_get_reflection_missing_object (MonoDomain *domain)
7321 {
7322         MonoObject *obj;
7323         static MonoClassField *missing_value_field = NULL;
7324         
7325         if (!missing_value_field) {
7326                 MonoClass *missing_klass;
7327                 missing_klass = mono_class_get_missing_class ();
7328                 mono_class_init (missing_klass);
7329                 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
7330                 g_assert (missing_value_field);
7331         }
7332         obj = mono_field_get_value_object (domain, missing_value_field, NULL); 
7333         g_assert (obj);
7334         return obj;
7335 }
7336
7337 static MonoObject*
7338 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
7339 {
7340         if (!*dbnull)
7341                 *dbnull = mono_get_dbnull_object (domain);
7342         return *dbnull;
7343 }
7344
7345 static MonoObject*
7346 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
7347 {
7348         if (!*reflection_missing)
7349                 *reflection_missing = mono_get_reflection_missing_object (domain);
7350         return *reflection_missing;
7351 }
7352
7353 /*
7354  * mono_param_get_objects:
7355  * @domain: an app domain
7356  * @method: a method
7357  *
7358  * Return an System.Reflection.ParameterInfo array object representing the parameters
7359  * in the method @method.
7360  */
7361 MonoArray*
7362 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
7363 {
7364         static MonoClass *System_Reflection_ParameterInfo;
7365         static MonoClass *System_Reflection_ParameterInfo_array;
7366         MonoError error;
7367         MonoArray *res = NULL;
7368         MonoReflectionMethod *member = NULL;
7369         MonoReflectionParameter *param = NULL;
7370         char **names = NULL, **blobs = NULL;
7371         guint32 *types = NULL;
7372         MonoType *type = NULL;
7373         MonoObject *dbnull = NULL;
7374         MonoObject *missing = NULL;
7375         MonoMarshalSpec **mspecs = NULL;
7376         MonoMethodSignature *sig = NULL;
7377         MonoVTable *pinfo_vtable;
7378         MonoReflectionType *rt;
7379         int i;
7380
7381         mono_error_init (&error);
7382         
7383         if (!System_Reflection_ParameterInfo_array) {
7384                 MonoClass *klass;
7385
7386                 klass = mono_class_get_mono_parameter_info_class ();
7387
7388                 mono_memory_barrier ();
7389                 System_Reflection_ParameterInfo = klass; 
7390
7391         
7392                 klass = mono_array_class_get (klass, 1);
7393                 mono_memory_barrier ();
7394                 System_Reflection_ParameterInfo_array = klass;
7395         }
7396
7397         sig = mono_method_signature_checked (method, &error);
7398         if (!mono_error_ok (&error))
7399                 goto leave;
7400
7401         if (!sig->param_count) {
7402                 res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0, &error);
7403                 if (!res)
7404                         goto leave;
7405
7406                 return res;
7407         }
7408
7409         /* Note: the cache is based on the address of the signature into the method
7410          * since we already cache MethodInfos with the method as keys.
7411          */
7412         CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
7413
7414         member = mono_method_get_object_checked (domain, method, refclass, &error);
7415         if (!member)
7416                 goto leave;
7417         names = g_new (char *, sig->param_count);
7418         mono_method_get_param_names (method, (const char **) names);
7419
7420         mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
7421         mono_method_get_marshal_info (method, mspecs);
7422
7423         res = mono_array_new_specific_checked (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count, &error);
7424         if (!res)
7425                 goto leave;
7426
7427         pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
7428         for (i = 0; i < sig->param_count; ++i) {
7429                 param = (MonoReflectionParameter *) mono_object_new_specific_checked (pinfo_vtable, &error);
7430                 if (!param)
7431                         goto leave;
7432
7433                 rt = mono_type_get_object_checked (domain, sig->params [i], &error);
7434                 if (!rt)
7435                         goto leave;
7436
7437                 MONO_OBJECT_SETREF (param, ClassImpl, rt);
7438
7439                 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
7440
7441                 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
7442
7443                 param->PositionImpl = i;
7444                 param->AttrsImpl = sig->params [i]->attrs;
7445
7446                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
7447                         if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7448                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7449                         else
7450                                 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7451                 } else {
7452
7453                         if (!blobs) {
7454                                 blobs = g_new0 (char *, sig->param_count);
7455                                 types = g_new0 (guint32, sig->param_count);
7456                                 get_default_param_value_blobs (method, blobs, types); 
7457                         }
7458
7459                         /* Build MonoType for the type from the Constant Table */
7460                         if (!type)
7461                                 type = g_new0 (MonoType, 1);
7462                         type->type = (MonoTypeEnum)types [i];
7463                         type->data.klass = NULL;
7464                         if (types [i] == MONO_TYPE_CLASS)
7465                                 type->data.klass = mono_defaults.object_class;
7466                         else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
7467                                 /* For enums, types [i] contains the base type */
7468
7469                                         type->type = MONO_TYPE_VALUETYPE;
7470                                         type->data.klass = mono_class_from_mono_type (sig->params [i]);
7471                         } else
7472                                 type->data.klass = mono_class_from_mono_type (type);
7473
7474                         MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
7475
7476                         /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
7477                         if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
7478                                 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
7479                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
7480                                 else
7481                                         MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
7482                         }
7483                         
7484                 }
7485
7486                 if (mspecs [i + 1]) {
7487                         MonoReflectionMarshalAsAttribute* mobj;
7488                         mobj = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [i + 1], &error);
7489                         if (!mobj)
7490                                 goto leave;
7491                         MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mobj);
7492                 }
7493                 
7494                 mono_array_setref (res, i, param);
7495         }
7496
7497 leave:
7498         g_free (names);
7499         g_free (blobs);
7500         g_free (types);
7501         g_free (type);
7502
7503         if (sig) {
7504                 for (i = sig->param_count; i >= 0; i--) {
7505                         if (mspecs [i])
7506                                 mono_metadata_free_marshal_spec (mspecs [i]);
7507                 }
7508         }
7509         g_free (mspecs);
7510
7511         mono_error_raise_exception (&error); /* FIXME don't raise here */
7512         
7513         CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
7514 }
7515
7516 MonoArray*
7517 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
7518 {
7519         return mono_param_get_objects_internal (domain, method, NULL);
7520 }
7521
7522 /*
7523  * mono_method_body_get_object:
7524  * @domain: an app domain
7525  * @method: a method
7526  *
7527  * Return an System.Reflection.MethodBody object representing the method @method.
7528  */
7529 MonoReflectionMethodBody*
7530 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
7531 {
7532         MonoError error;
7533         MonoReflectionMethodBody *ret;
7534         MonoMethodHeader *header;
7535         MonoImage *image;
7536         MonoReflectionType *rt;
7537         guint32 method_rva, local_var_sig_token;
7538     char *ptr;
7539         unsigned char format, flags;
7540         int i;
7541
7542         /* for compatibility with .net */
7543     if (method_is_dynamic (method))
7544         mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7545
7546         CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
7547
7548         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7549                 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
7550             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
7551                 (method->klass->image->raw_data && method->klass->image->raw_data [1] != 'Z') ||
7552             (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
7553                 return NULL;
7554
7555         image = method->klass->image;
7556         header = mono_method_get_header (method);
7557
7558         if (!image_is_dynamic (image)) {
7559                 /* Obtain local vars signature token */
7560                 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
7561                 ptr = mono_image_rva_map (image, method_rva);
7562                 flags = *(const unsigned char *) ptr;
7563                 format = flags & METHOD_HEADER_FORMAT_MASK;
7564                 switch (format){
7565                 case METHOD_HEADER_TINY_FORMAT:
7566                         local_var_sig_token = 0;
7567                         break;
7568                 case METHOD_HEADER_FAT_FORMAT:
7569                         ptr += 2;
7570                         ptr += 2;
7571                         ptr += 4;
7572                         local_var_sig_token = read32 (ptr);
7573                         break;
7574                 default:
7575                         g_assert_not_reached ();
7576                 }
7577         } else
7578                 local_var_sig_token = 0; //FIXME
7579
7580         ret = (MonoReflectionMethodBody*)mono_object_new_checked (domain, mono_class_get_method_body_class (), &error);
7581         mono_error_raise_exception (&error); /* FIXME don't raise here */
7582
7583         ret->init_locals = header->init_locals;
7584         ret->max_stack = header->max_stack;
7585         ret->local_var_sig_token = local_var_sig_token;
7586         MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
7587         memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
7588
7589         /* Locals */
7590         MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, mono_class_get_local_variable_info_class (), header->num_locals));
7591         for (i = 0; i < header->num_locals; ++i) {
7592                 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new_checked (domain, mono_class_get_local_variable_info_class (), &error);
7593                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7594
7595                 rt = mono_type_get_object_checked (domain, header->locals [i], &error);
7596                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7597
7598                 MONO_OBJECT_SETREF (info, local_type, rt);
7599
7600                 info->is_pinned = header->locals [i]->pinned;
7601                 info->local_index = i;
7602                 mono_array_setref (ret->locals, i, info);
7603         }
7604
7605         /* Exceptions */
7606         MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, mono_class_get_exception_handling_clause_class (), header->num_clauses));
7607         for (i = 0; i < header->num_clauses; ++i) {
7608                 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new_checked (domain, mono_class_get_exception_handling_clause_class (), &error);
7609                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7610                 MonoExceptionClause *clause = &header->clauses [i];
7611
7612                 info->flags = clause->flags;
7613                 info->try_offset = clause->try_offset;
7614                 info->try_length = clause->try_len;
7615                 info->handler_offset = clause->handler_offset;
7616                 info->handler_length = clause->handler_len;
7617                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
7618                         info->filter_offset = clause->data.filter_offset;
7619                 else if (clause->data.catch_class) {
7620                         rt = mono_type_get_object_checked (mono_domain_get (), &clause->data.catch_class->byval_arg, &error);
7621                         mono_error_raise_exception (&error); /* FIXME don't raise here */
7622
7623                         MONO_OBJECT_SETREF (info, catch_type, rt);
7624                 }
7625
7626                 mono_array_setref (ret->clauses, i, info);
7627         }
7628
7629         mono_metadata_free_mh (header);
7630         CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7631         return ret;
7632 }
7633
7634 /**
7635  * mono_get_dbnull_object:
7636  * @domain: Domain where the object lives
7637  *
7638  * Returns the System.DBNull.Value singleton object
7639  *
7640  * Used as the value for ParameterInfo.DefaultValue 
7641  */
7642 MonoObject *
7643 mono_get_dbnull_object (MonoDomain *domain)
7644 {
7645         MonoObject *obj;
7646         static MonoClassField *dbnull_value_field = NULL;
7647         
7648         if (!dbnull_value_field) {
7649                 MonoClass *dbnull_klass;
7650                 dbnull_klass = mono_class_get_dbnull_class ();
7651                 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7652                 g_assert (dbnull_value_field);
7653         }
7654         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
7655         g_assert (obj);
7656         return obj;
7657 }
7658
7659 static void
7660 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7661 {
7662         guint32 param_index, i, lastp, crow = 0;
7663         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7664         gint32 idx;
7665
7666         MonoClass *klass = method->klass;
7667         MonoImage *image = klass->image;
7668         MonoMethodSignature *methodsig = mono_method_signature (method);
7669
7670         MonoTableInfo *constt;
7671         MonoTableInfo *methodt;
7672         MonoTableInfo *paramt;
7673
7674         if (!methodsig->param_count)
7675                 return;
7676
7677         mono_class_init (klass);
7678
7679         if (image_is_dynamic (klass->image)) {
7680                 MonoReflectionMethodAux *aux;
7681                 if (method->is_inflated)
7682                         method = ((MonoMethodInflated*)method)->declaring;
7683                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7684                 if (aux && aux->param_defaults) {
7685                         memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7686                         memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7687                 }
7688                 return;
7689         }
7690
7691         methodt = &klass->image->tables [MONO_TABLE_METHOD];
7692         paramt = &klass->image->tables [MONO_TABLE_PARAM];
7693         constt = &image->tables [MONO_TABLE_CONSTANT];
7694
7695         idx = mono_method_get_index (method) - 1;
7696         g_assert (idx != -1);
7697
7698         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7699         if (idx + 1 < methodt->rows)
7700                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7701         else
7702                 lastp = paramt->rows + 1;
7703
7704         for (i = param_index; i < lastp; ++i) {
7705                 guint32 paramseq;
7706
7707                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7708                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7709
7710                 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7711                         continue;
7712
7713                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7714                 if (!crow) {
7715                         continue;
7716                 }
7717         
7718                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7719                 blobs [paramseq - 1] = (char *)mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7720                 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7721         }
7722
7723         return;
7724 }
7725
7726 MonoObject *
7727 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7728 {
7729         MonoError error;
7730         void *retval;
7731         MonoClass *klass;
7732         MonoObject *object;
7733         MonoType *basetype = type;
7734
7735         if (!blob)
7736                 return NULL;
7737         
7738         klass = mono_class_from_mono_type (type);
7739         if (klass->valuetype) {
7740                 object = mono_object_new_checked (domain, klass, &error);
7741                 mono_error_raise_exception (&error); /* FIXME don't raise here */
7742                 retval = ((gchar *) object + sizeof (MonoObject));
7743                 if (klass->enumtype)
7744                         basetype = mono_class_enum_basetype (klass);
7745         } else {
7746                 retval = &object;
7747         }
7748                         
7749         if (!mono_get_constant_value_from_blob (domain, basetype->type,  blob, retval))
7750                 return object;
7751         else
7752                 return NULL;
7753 }
7754
7755 static int
7756 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7757         int found_sep;
7758         char *s;
7759         gboolean quoted = FALSE;
7760
7761         memset (assembly, 0, sizeof (MonoAssemblyName));
7762         assembly->culture = "";
7763         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7764
7765         if (*p == '"') {
7766                 quoted = TRUE;
7767                 p++;
7768         }
7769         assembly->name = p;
7770         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7771                 p++;
7772         if (quoted) {
7773                 if (*p != '"')
7774                         return 1;
7775                 *p = 0;
7776                 p++;
7777         }
7778         if (*p != ',')
7779                 return 1;
7780         *p = 0;
7781         /* Remove trailing whitespace */
7782         s = p - 1;
7783         while (*s && g_ascii_isspace (*s))
7784                 *s-- = 0;
7785         p ++;
7786         while (g_ascii_isspace (*p))
7787                 p++;
7788         while (*p) {
7789                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7790                         p += 8;
7791                         assembly->major = strtoul (p, &s, 10);
7792                         if (s == p || *s != '.')
7793                                 return 1;
7794                         p = ++s;
7795                         assembly->minor = strtoul (p, &s, 10);
7796                         if (s == p || *s != '.')
7797                                 return 1;
7798                         p = ++s;
7799                         assembly->build = strtoul (p, &s, 10);
7800                         if (s == p || *s != '.')
7801                                 return 1;
7802                         p = ++s;
7803                         assembly->revision = strtoul (p, &s, 10);
7804                         if (s == p)
7805                                 return 1;
7806                         p = s;
7807                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7808                         p += 8;
7809                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7810                                 assembly->culture = "";
7811                                 p += 7;
7812                         } else {
7813                                 assembly->culture = p;
7814                                 while (*p && *p != ',') {
7815                                         p++;
7816                                 }
7817                         }
7818                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7819                         p += 15;
7820                         if (strncmp (p, "null", 4) == 0) {
7821                                 p += 4;
7822                         } else {
7823                                 int len;
7824                                 gchar *start = p;
7825                                 while (*p && *p != ',') {
7826                                         p++;
7827                                 }
7828                                 len = (p - start + 1);
7829                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7830                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7831                                 g_strlcpy ((char*)assembly->public_key_token, start, len);
7832                         }
7833                 } else {
7834                         while (*p && *p != ',')
7835                                 p++;
7836                 }
7837                 found_sep = 0;
7838                 while (g_ascii_isspace (*p) || *p == ',') {
7839                         *p++ = 0;
7840                         found_sep = 1;
7841                         continue;
7842                 }
7843                 /* failed */
7844                 if (!found_sep)
7845                         return 1;
7846         }
7847
7848         return 0;
7849 }
7850
7851 /*
7852  * mono_reflection_parse_type:
7853  * @name: type name
7854  *
7855  * Parse a type name as accepted by the GetType () method and output the info
7856  * extracted in the info structure.
7857  * the name param will be mangled, so, make a copy before passing it to this function.
7858  * The fields in info will be valid until the memory pointed to by name is valid.
7859  *
7860  * See also mono_type_get_name () below.
7861  *
7862  * Returns: 0 on parse error.
7863  */
7864 static int
7865 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7866                              MonoTypeNameParse *info)
7867 {
7868         char *start, *p, *w, *last_point, *startn;
7869         int in_modifiers = 0;
7870         int isbyref = 0, rank = 0, isptr = 0;
7871
7872         start = p = w = name;
7873
7874         //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7875         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7876         info->name = info->name_space = NULL;
7877         info->nested = NULL;
7878         info->modifiers = NULL;
7879         info->type_arguments = NULL;
7880
7881         /* last_point separates the namespace from the name */
7882         last_point = NULL;
7883         /* Skips spaces */
7884         while (*p == ' ') p++, start++, w++, name++;
7885
7886         while (*p) {
7887                 switch (*p) {
7888                 case '+':
7889                         *p = 0; /* NULL terminate the name */
7890                         startn = p + 1;
7891                         info->nested = g_list_append (info->nested, startn);
7892                         /* we have parsed the nesting namespace + name */
7893                         if (info->name)
7894                                 break;
7895                         if (last_point) {
7896                                 info->name_space = start;
7897                                 *last_point = 0;
7898                                 info->name = last_point + 1;
7899                         } else {
7900                                 info->name_space = (char *)"";
7901                                 info->name = start;
7902                         }
7903                         break;
7904                 case '.':
7905                         last_point = p;
7906                         break;
7907                 case '\\':
7908                         ++p;
7909                         break;
7910                 case '&':
7911                 case '*':
7912                 case '[':
7913                 case ',':
7914                 case ']':
7915                         in_modifiers = 1;
7916                         break;
7917                 default:
7918                         break;
7919                 }
7920                 if (in_modifiers)
7921                         break;
7922                 // *w++ = *p++;
7923                 p++;
7924         }
7925         
7926         if (!info->name) {
7927                 if (last_point) {
7928                         info->name_space = start;
7929                         *last_point = 0;
7930                         info->name = last_point + 1;
7931                 } else {
7932                         info->name_space = (char *)"";
7933                         info->name = start;
7934                 }
7935         }
7936         while (*p) {
7937                 switch (*p) {
7938                 case '&':
7939                         if (isbyref) /* only one level allowed by the spec */
7940                                 return 0;
7941                         isbyref = 1;
7942                         isptr = 0;
7943                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7944                         *p++ = 0;
7945                         break;
7946                 case '*':
7947                         if (isbyref) /* pointer to ref not okay */
7948                                 return 0;
7949                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7950                         isptr = 1;
7951                         *p++ = 0;
7952                         break;
7953                 case '[':
7954                         if (isbyref) /* array of ref and generic ref are not okay */
7955                                 return 0;
7956                         //Decide if it's an array of a generic argument list
7957                         *p++ = 0;
7958
7959                         if (!*p) //XXX test
7960                                 return 0;
7961                         if (*p  == ',' || *p == '*' || *p == ']') { //array
7962                                 isptr = 0;
7963                                 rank = 1;
7964                                 while (*p) {
7965                                         if (*p == ']')
7966                                                 break;
7967                                         if (*p == ',')
7968                                                 rank++;
7969                                         else if (*p == '*') /* '*' means unknown lower bound */
7970                                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7971                                         else
7972                                                 return 0;
7973                                         ++p;
7974                                 }
7975                                 if (*p++ != ']')
7976                                         return 0;
7977                                 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7978                         } else {
7979                                 if (rank || isptr) /* generic args after array spec or ptr*/ //XXX test
7980                                         return 0;
7981                                 isptr = 0;
7982                                 info->type_arguments = g_ptr_array_new ();
7983                                 while (*p) {
7984                                         MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7985                                         gboolean fqname = FALSE;
7986
7987                                         g_ptr_array_add (info->type_arguments, subinfo);
7988
7989                                         while (*p == ' ') p++;
7990                                         if (*p == '[') {
7991                                                 p++;
7992                                                 fqname = TRUE;
7993                                         }
7994
7995                                         if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7996                                                 return 0;
7997
7998                                         /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7999                                         if (fqname && (*p != ']')) {
8000                                                 char *aname;
8001
8002                                                 if (*p != ',')
8003                                                         return 0;
8004                                                 *p++ = 0;
8005
8006                                                 aname = p;
8007                                                 while (*p && (*p != ']'))
8008                                                         p++;
8009
8010                                                 if (*p != ']')
8011                                                         return 0;
8012
8013                                                 *p++ = 0;
8014                                                 while (*aname) {
8015                                                         if (g_ascii_isspace (*aname)) {
8016                                                                 ++aname;
8017                                                                 continue;
8018                                                         }
8019                                                         break;
8020                                                 }
8021                                                 if (!*aname ||
8022                                                     !assembly_name_to_aname (&subinfo->assembly, aname))
8023                                                         return 0;
8024                                         } else if (fqname && (*p == ']')) {
8025                                                 *p++ = 0;
8026                                         }
8027                                         if (*p == ']') {
8028                                                 *p++ = 0;
8029                                                 break;
8030                                         } else if (!*p) {
8031                                                 return 0;
8032                                         }
8033                                         *p++ = 0;
8034                                 }
8035                         }
8036                         break;
8037                 case ']':
8038                         if (is_recursed)
8039                                 goto end;
8040                         return 0;
8041                 case ',':
8042                         if (is_recursed)
8043                                 goto end;
8044                         *p++ = 0;
8045                         while (*p) {
8046                                 if (g_ascii_isspace (*p)) {
8047                                         ++p;
8048                                         continue;
8049                                 }
8050                                 break;
8051                         }
8052                         if (!*p)
8053                                 return 0; /* missing assembly name */
8054                         if (!assembly_name_to_aname (&info->assembly, p))
8055                                 return 0;
8056                         break;
8057                 default:
8058                         return 0;
8059                 }
8060                 if (info->assembly.name)
8061                         break;
8062         }
8063         // *w = 0; /* terminate class name */
8064  end:
8065         if (!info->name || !*info->name)
8066                 return 0;
8067         if (endptr)
8068                 *endptr = p;
8069         /* add other consistency checks */
8070         return 1;
8071 }
8072
8073
8074 /**
8075  * mono_identifier_unescape_type_name_chars:
8076  * @identifier: the display name of a mono type
8077  *
8078  * Returns:
8079  *  The name in internal form, that is without escaping backslashes.
8080  *
8081  *  The string is modified in place!
8082  */
8083 char*
8084 mono_identifier_unescape_type_name_chars(char* identifier)
8085 {
8086         char *w, *r;
8087         if (!identifier)
8088                 return NULL;
8089         for (w = r = identifier; *r != 0; r++)
8090         {
8091                 char c = *r;
8092                 if (c == '\\') {
8093                         r++;
8094                         if (*r == 0)
8095                                 break;
8096                         c = *r;
8097                 }
8098                 *w = c;
8099                 w++;
8100         }
8101         if (w != r)
8102                 *w = 0;
8103         return identifier;
8104 }
8105
8106 void
8107 mono_identifier_unescape_info (MonoTypeNameParse* info);
8108
8109 static void
8110 unescape_each_type_argument(void* data, void* user_data)
8111 {
8112         MonoTypeNameParse* info = (MonoTypeNameParse*)data;
8113         mono_identifier_unescape_info (info);
8114 }
8115
8116 static void
8117 unescape_each_nested_name (void* data, void* user_data)
8118 {
8119         char* nested_name = (char*) data;
8120         mono_identifier_unescape_type_name_chars(nested_name);
8121 }
8122
8123 /**
8124  * mono_identifier_unescape_info:
8125  *
8126  * @info: a parsed display form of an (optionally assembly qualified) full type name.
8127  *
8128  * Returns: nothing.
8129  *
8130  * Destructively updates the info by unescaping the identifiers that
8131  * comprise the type namespace, name, nested types (if any) and
8132  * generic type arguments (if any).
8133  *
8134  * The resulting info has the names in internal form.
8135  *
8136  */
8137 void
8138 mono_identifier_unescape_info (MonoTypeNameParse *info)
8139 {
8140         if (!info)
8141                 return;
8142         mono_identifier_unescape_type_name_chars(info->name_space);
8143         mono_identifier_unescape_type_name_chars(info->name);
8144         // but don't escape info->assembly
8145         if (info->type_arguments)
8146                 g_ptr_array_foreach(info->type_arguments, &unescape_each_type_argument, NULL);
8147         if (info->nested)
8148                 g_list_foreach(info->nested, &unescape_each_nested_name, NULL);
8149 }
8150
8151 int
8152 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
8153 {
8154         int ok = _mono_reflection_parse_type (name, NULL, FALSE, info);
8155         if (ok) {
8156                 mono_identifier_unescape_info (info);
8157         }
8158         return ok;
8159 }
8160
8161 static MonoType*
8162 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
8163 {
8164         gboolean type_resolve = FALSE;
8165         MonoType *type;
8166         MonoImage *rootimage = image;
8167
8168         if (info->assembly.name) {
8169                 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
8170                 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
8171                         /* 
8172                          * This could happen in the AOT compiler case when the search hook is not
8173                          * installed.
8174                          */
8175                         assembly = image->assembly;
8176                 if (!assembly) {
8177                         /* then we must load the assembly ourselve - see #60439 */
8178                         assembly = mono_assembly_load (&info->assembly, image->assembly->basedir, NULL);
8179                         if (!assembly)
8180                                 return NULL;
8181                 }
8182                 image = assembly->image;
8183         } else if (!image) {
8184                 image = mono_defaults.corlib;
8185         }
8186
8187         type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8188         if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
8189                 image = mono_defaults.corlib;
8190                 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
8191         }
8192
8193         return type;
8194 }
8195
8196 /**
8197  * mono_reflection_get_type_internal:
8198  *
8199  * Returns: may return NULL on success, sets error on failure.
8200  */
8201 static MonoType*
8202 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8203 {
8204         MonoClass *klass;
8205         GList *mod;
8206         int modval;
8207         gboolean bounded = FALSE;
8208         
8209         mono_error_init (error);
8210         if (!image)
8211                 image = mono_defaults.corlib;
8212
8213         if (!rootimage)
8214                 rootimage = mono_defaults.corlib;
8215
8216         if (ignorecase)
8217                 klass = mono_class_from_name_case_checked (image, info->name_space, info->name, error);
8218         else
8219                 klass = mono_class_from_name_checked (image, info->name_space, info->name, error);
8220
8221         if (!klass)
8222                 return NULL;
8223
8224         for (mod = info->nested; mod; mod = mod->next) {
8225                 gpointer iter = NULL;
8226                 MonoClass *parent;
8227
8228                 parent = klass;
8229                 mono_class_init (parent);
8230
8231                 while ((klass = mono_class_get_nested_types (parent, &iter))) {
8232                         char *lastp;
8233                         char *nested_name, *nested_nspace;
8234                         gboolean match = TRUE;
8235
8236                         lastp = strrchr ((const char *)mod->data, '.');
8237                         if (lastp) {
8238                                 /* Nested classes can have namespaces */
8239                                 int nspace_len;
8240
8241                                 nested_name = g_strdup (lastp + 1);
8242                                 nspace_len = lastp - (char*)mod->data;
8243                                 nested_nspace = (char *)g_malloc (nspace_len + 1);
8244                                 memcpy (nested_nspace, mod->data, nspace_len);
8245                                 nested_nspace [nspace_len] = '\0';
8246
8247                         } else {
8248                                 nested_name = (char *)mod->data;
8249                                 nested_nspace = NULL;
8250                         }
8251
8252                         if (nested_nspace) {
8253                                 if (ignorecase) {
8254                                         if (!(klass->name_space && mono_utf8_strcasecmp (klass->name_space, nested_nspace) == 0))
8255                                                 match = FALSE;
8256                                 } else {
8257                                         if (!(klass->name_space && strcmp (klass->name_space, nested_nspace) == 0))
8258                                                 match = FALSE;
8259                                 }
8260                         }
8261                         if (match) {
8262                                 if (ignorecase) {
8263                                         if (mono_utf8_strcasecmp (klass->name, nested_name) != 0)
8264                                                 match = FALSE;
8265                                 } else {
8266                                         if (strcmp (klass->name, nested_name) != 0)
8267                                                 match = FALSE;
8268                                 }
8269                         }
8270                         if (lastp) {
8271                                 g_free (nested_name);
8272                                 g_free (nested_nspace);
8273                         }
8274                         if (match)
8275                                 break;
8276                 }
8277
8278                 if (!klass)
8279                         break;
8280         }
8281         if (!klass)
8282                 return NULL;
8283
8284         if (info->type_arguments) {
8285                 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
8286                 MonoReflectionType *the_type;
8287                 MonoType *instance;
8288                 int i;
8289
8290                 for (i = 0; i < info->type_arguments->len; i++) {
8291                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8292
8293                         type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
8294                         if (!type_args [i]) {
8295                                 g_free (type_args);
8296                                 return NULL;
8297                         }
8298                 }
8299
8300                 the_type = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
8301                 if (!the_type)
8302                         return NULL;
8303
8304                 instance = mono_reflection_bind_generic_parameters (
8305                         the_type, info->type_arguments->len, type_args);
8306
8307                 g_free (type_args);
8308                 if (!instance)
8309                         return NULL;
8310
8311                 klass = mono_class_from_mono_type (instance);
8312         }
8313
8314         for (mod = info->modifiers; mod; mod = mod->next) {
8315                 modval = GPOINTER_TO_UINT (mod->data);
8316                 if (!modval) { /* byref: must be last modifier */
8317                         return &klass->this_arg;
8318                 } else if (modval == -1) {
8319                         klass = mono_ptr_class_get (&klass->byval_arg);
8320                 } else if (modval == -2) {
8321                         bounded = TRUE;
8322                 } else { /* array rank */
8323                         klass = mono_bounded_array_class_get (klass, modval, bounded);
8324                 }
8325         }
8326
8327         return &klass->byval_arg;
8328 }
8329
8330 /*
8331  * mono_reflection_get_type:
8332  * @image: a metadata context
8333  * @info: type description structure
8334  * @ignorecase: flag for case-insensitive string compares
8335  * @type_resolve: whenever type resolve was already tried
8336  *
8337  * Build a MonoType from the type description in @info.
8338  * 
8339  */
8340
8341 MonoType*
8342 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
8343         return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
8344 }
8345
8346 static MonoType*
8347 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase, MonoError *error)
8348 {
8349         MonoReflectionAssemblyBuilder *abuilder;
8350         MonoType *type;
8351         int i;
8352
8353         mono_error_init (error);
8354         g_assert (assembly_is_dynamic (assembly));
8355         abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object_checked (((MonoDynamicAssembly*)assembly)->domain, assembly, error);
8356         if (!abuilder)
8357                 return NULL;
8358
8359         /* Enumerate all modules */
8360
8361         type = NULL;
8362         if (abuilder->modules) {
8363                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
8364                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
8365                         type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase, error);
8366                         if (type)
8367                                 break;
8368                         if (!mono_error_ok (error))
8369                                 return NULL;
8370                 }
8371         }
8372
8373         if (!type && abuilder->loaded_modules) {
8374                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
8375                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
8376                         type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase, error);
8377                         if (type)
8378                                 break;
8379                         if (!mono_error_ok (error))
8380                                 return NULL;
8381                 }
8382         }
8383
8384         return type;
8385 }
8386         
8387 MonoType*
8388 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
8389 {
8390         MonoError error;
8391         MonoType *type;
8392         MonoReflectionAssembly *assembly;
8393         GString *fullName;
8394         GList *mod;
8395
8396         if (image && image_is_dynamic (image))
8397                 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase, &error);
8398         else {
8399                 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase, &error);
8400         }
8401         if (!mono_error_ok (&error))
8402                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8403
8404         if (type)
8405                 return type;
8406         if (!mono_domain_has_type_resolve (mono_domain_get ()))
8407                 return NULL;
8408
8409         if (type_resolve) {
8410                 if (*type_resolve) 
8411                         return NULL;
8412                 else
8413                         *type_resolve = TRUE;
8414         }
8415         
8416         /* Reconstruct the type name */
8417         fullName = g_string_new ("");
8418         if (info->name_space && (info->name_space [0] != '\0'))
8419                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
8420         else
8421                 g_string_printf (fullName, "%s", info->name);
8422         for (mod = info->nested; mod; mod = mod->next)
8423                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
8424
8425         assembly = mono_domain_try_type_resolve_checked ( mono_domain_get (), fullName->str, NULL, &error);
8426         mono_error_raise_exception (&error); /* FIXME don't raise here */
8427
8428         if (assembly) {
8429                 if (assembly_is_dynamic (assembly->assembly))
8430                         type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly,
8431                                                                           info, ignorecase, &error);
8432                 else
8433                         type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image, 
8434                                                                   info, ignorecase, &error);
8435         }
8436         g_string_free (fullName, TRUE);
8437         if (!mono_error_ok (&error))
8438                 mono_error_raise_exception (&error); /* FIXME don't raise here */
8439         return type;
8440 }
8441
8442 void
8443 mono_reflection_free_type_info (MonoTypeNameParse *info)
8444 {
8445         g_list_free (info->modifiers);
8446         g_list_free (info->nested);
8447
8448         if (info->type_arguments) {
8449                 int i;
8450
8451                 for (i = 0; i < info->type_arguments->len; i++) {
8452                         MonoTypeNameParse *subinfo = (MonoTypeNameParse *)g_ptr_array_index (info->type_arguments, i);
8453
8454                         mono_reflection_free_type_info (subinfo);
8455                         /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
8456                         g_free (subinfo);
8457                 }
8458
8459                 g_ptr_array_free (info->type_arguments, TRUE);
8460         }
8461 }
8462
8463 /*
8464  * mono_reflection_type_from_name:
8465  * @name: type name.
8466  * @image: a metadata context (can be NULL).
8467  *
8468  * Retrieves a MonoType from its @name. If the name is not fully qualified,
8469  * it defaults to get the type from @image or, if @image is NULL or loading
8470  * from it fails, uses corlib.
8471  * 
8472  */
8473 MonoType*
8474 mono_reflection_type_from_name (char *name, MonoImage *image)
8475 {
8476         MonoType *type = NULL;
8477         MonoTypeNameParse info;
8478         char *tmp;
8479
8480         /* Make a copy since parse_type modifies its argument */
8481         tmp = g_strdup (name);
8482         
8483         /*g_print ("requested type %s\n", str);*/
8484         if (mono_reflection_parse_type (tmp, &info)) {
8485                 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
8486         }
8487
8488         g_free (tmp);
8489         mono_reflection_free_type_info (&info);
8490         return type;
8491 }
8492
8493 /*
8494  * mono_reflection_get_token:
8495  *
8496  *   Return the metadata token of OBJ which should be an object
8497  * representing a metadata element.
8498  */
8499 guint32
8500 mono_reflection_get_token (MonoObject *obj)
8501 {
8502         MonoClass *klass;
8503         guint32 token = 0;
8504
8505         klass = obj->vtable->klass;
8506
8507         if (strcmp (klass->name, "MethodBuilder") == 0) {
8508                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
8509
8510                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8511         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
8512                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
8513
8514                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
8515         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
8516                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
8517
8518                 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
8519         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
8520                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
8521                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
8522         } else if (strcmp (klass->name, "MonoType") == 0) {
8523                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
8524                 MonoClass *mc = mono_class_from_mono_type (type);
8525                 if (!mono_class_init (mc))
8526                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
8527
8528                 token = mc->type_token;
8529         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
8530                    strcmp (klass->name, "MonoMethod") == 0 ||
8531                    strcmp (klass->name, "MonoGenericMethod") == 0 ||
8532                    strcmp (klass->name, "MonoGenericCMethod") == 0) {
8533                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
8534                 if (m->method->is_inflated) {
8535                         MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
8536                         return inflated->declaring->token;
8537                 } else {
8538                         token = m->method->token;
8539                 }
8540         } else if (strcmp (klass->name, "MonoField") == 0) {
8541                 MonoReflectionField *f = (MonoReflectionField*)obj;
8542
8543                 if (is_field_on_inst (f->field)) {
8544                         MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
8545
8546                         if (f->field >= dgclass->fields && f->field < dgclass->fields + dgclass->count_fields) {
8547                                 int field_index = f->field - dgclass->fields;
8548                                 MonoObject *obj;
8549
8550                                 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
8551                                 obj = dgclass->field_objects [field_index];
8552                                 return mono_reflection_get_token (obj);
8553                         }
8554                 }
8555                 token = mono_class_get_field_token (f->field);
8556         } else if (strcmp (klass->name, "MonoProperty") == 0) {
8557                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
8558
8559                 token = mono_class_get_property_token (p->property);
8560         } else if (strcmp (klass->name, "MonoEvent") == 0) {
8561                 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
8562
8563                 token = mono_class_get_event_token (p->event);
8564         } else if (strcmp (klass->name, "ParameterInfo") == 0 || strcmp (klass->name, "MonoParameterInfo") == 0) {
8565                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
8566                 MonoClass *member_class = mono_object_class (p->MemberImpl);
8567                 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
8568
8569                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
8570         } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
8571                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
8572
8573                 token = m->token;
8574         } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
8575                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
8576         } else {
8577                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
8578                 MonoException *ex = mono_get_exception_not_implemented (msg);
8579                 g_free (msg);
8580                 mono_raise_exception (ex);
8581         }
8582
8583         return token;
8584 }
8585
8586 static MonoClass*
8587 load_cattr_enum_type (MonoImage *image, const char *p, const char **end, MonoError *error)
8588 {
8589         char *n;
8590         MonoType *t;
8591         int slen = mono_metadata_decode_value (p, &p);
8592
8593         mono_error_init (error);
8594
8595         n = (char *)g_memdup (p, slen + 1);
8596         n [slen] = 0;
8597         t = mono_reflection_type_from_name (n, image);
8598         if (!t) {
8599                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8600                 /* We don't free n, it's consumed by mono_error */
8601                 mono_error_set_type_load_name (error, n, NULL, "Could not load enum type %s while decoding custom attribute", n);
8602                 return NULL;
8603         }
8604         g_free (n);
8605         p += slen;
8606         *end = p;
8607         return mono_class_from_mono_type (t);
8608 }
8609
8610 static void*
8611 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end, MonoError *error)
8612 {
8613         int slen, type = t->type;
8614         MonoClass *tklass = t->data.klass;
8615
8616         mono_error_init (error);
8617
8618 handle_enum:
8619         switch (type) {
8620         case MONO_TYPE_U1:
8621         case MONO_TYPE_I1:
8622         case MONO_TYPE_BOOLEAN: {
8623                 MonoBoolean *bval = (MonoBoolean *)g_malloc (sizeof (MonoBoolean));
8624                 *bval = *p;
8625                 *end = p + 1;
8626                 return bval;
8627         }
8628         case MONO_TYPE_CHAR:
8629         case MONO_TYPE_U2:
8630         case MONO_TYPE_I2: {
8631                 guint16 *val = (guint16 *)g_malloc (sizeof (guint16));
8632                 *val = read16 (p);
8633                 *end = p + 2;
8634                 return val;
8635         }
8636 #if SIZEOF_VOID_P == 4
8637         case MONO_TYPE_U:
8638         case MONO_TYPE_I:
8639 #endif
8640         case MONO_TYPE_R4:
8641         case MONO_TYPE_U4:
8642         case MONO_TYPE_I4: {
8643                 guint32 *val = (guint32 *)g_malloc (sizeof (guint32));
8644                 *val = read32 (p);
8645                 *end = p + 4;
8646                 return val;
8647         }
8648 #if SIZEOF_VOID_P == 8
8649         case MONO_TYPE_U: /* error out instead? this should probably not happen */
8650         case MONO_TYPE_I:
8651 #endif
8652         case MONO_TYPE_U8:
8653         case MONO_TYPE_I8: {
8654                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8655                 *val = read64 (p);
8656                 *end = p + 8;
8657                 return val;
8658         }
8659         case MONO_TYPE_R8: {
8660                 double *val = (double *)g_malloc (sizeof (double));
8661                 readr8 (p, val);
8662                 *end = p + 8;
8663                 return val;
8664         }
8665         case MONO_TYPE_VALUETYPE:
8666                 if (t->data.klass->enumtype) {
8667                         type = mono_class_enum_basetype (t->data.klass)->type;
8668                         goto handle_enum;
8669                 } else {
8670                         MonoClass *k =  t->data.klass;
8671                         
8672                         if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
8673                                 guint64 *val = (guint64 *)g_malloc (sizeof (guint64));
8674                                 *val = read64 (p);
8675                                 *end = p + 8;
8676                                 return val;
8677                         }
8678                 }
8679                 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
8680                 break;
8681                 
8682         case MONO_TYPE_STRING:
8683                 if (*p == (char)0xFF) {
8684                         *end = p + 1;
8685                         return NULL;
8686                 }
8687                 slen = mono_metadata_decode_value (p, &p);
8688                 *end = p + slen;
8689                 return mono_string_new_len (mono_domain_get (), p, slen);
8690         case MONO_TYPE_CLASS: {
8691                 MonoReflectionType *rt;
8692                 char *n;
8693                 MonoType *t;
8694                 if (*p == (char)0xFF) {
8695                         *end = p + 1;
8696                         return NULL;
8697                 }
8698 handle_type:
8699                 slen = mono_metadata_decode_value (p, &p);
8700                 n = (char *)g_memdup (p, slen + 1);
8701                 n [slen] = 0;
8702                 t = mono_reflection_type_from_name (n, image);
8703                 if (!t) {
8704                         /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8705                         /* We don't free n, it's consumed by mono_error */
8706                         mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8707                         return NULL;
8708                 }
8709                 g_free (n);
8710                 *end = p + slen;
8711
8712                 rt = mono_type_get_object_checked (mono_domain_get (), t, error);
8713                 if (!mono_error_ok (error))
8714                         return NULL;
8715
8716                 return rt;
8717         }
8718         case MONO_TYPE_OBJECT: {
8719                 char subt = *p++;
8720                 MonoObject *obj;
8721                 MonoClass *subc = NULL;
8722                 void *val;
8723
8724                 if (subt == 0x50) {
8725                         goto handle_type;
8726                 } else if (subt == 0x0E) {
8727                         type = MONO_TYPE_STRING;
8728                         goto handle_enum;
8729                 } else if (subt == 0x1D) {
8730                         MonoType simple_type = {{0}};
8731                         int etype = *p;
8732                         p ++;
8733
8734                         type = MONO_TYPE_SZARRAY;
8735                         if (etype == 0x50) {
8736                                 tklass = mono_defaults.systemtype_class;
8737                         } else if (etype == 0x55) {
8738                                 tklass = load_cattr_enum_type (image, p, &p, error);
8739                                 if (!mono_error_ok (error))
8740                                         return NULL;
8741                         } else {
8742                                 if (etype == 0x51)
8743                                         /* See Partition II, Appendix B3 */
8744                                         etype = MONO_TYPE_OBJECT;
8745                                 simple_type.type = (MonoTypeEnum)etype;
8746                                 tklass = mono_class_from_mono_type (&simple_type);
8747                         }
8748                         goto handle_enum;
8749                 } else if (subt == 0x55) {
8750                         char *n;
8751                         MonoType *t;
8752                         slen = mono_metadata_decode_value (p, &p);
8753                         n = (char *)g_memdup (p, slen + 1);
8754                         n [slen] = 0;
8755                         t = mono_reflection_type_from_name (n, image);
8756                         if (!t) {
8757                                 /* FIXME the error should come from mono_reflection_type_from_name as it will have type/assembly names split */
8758                                 /* We don't free n, it's consumed by mono_error */
8759                                 mono_error_set_type_load_name (error, n, NULL, "Could not load type %s while decoding custom attribute", n);
8760                                 return NULL;
8761                         }
8762                         g_free (n);
8763                         p += slen;
8764                         subc = mono_class_from_mono_type (t);
8765                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
8766                         MonoType simple_type = {{0}};
8767                         simple_type.type = (MonoTypeEnum)subt;
8768                         subc = mono_class_from_mono_type (&simple_type);
8769                 } else {
8770                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
8771                 }
8772                 val = load_cattr_value (image, &subc->byval_arg, p, end, error);
8773                 obj = NULL;
8774                 if (mono_error_ok (error)) {
8775                         obj = mono_object_new_checked (mono_domain_get (), subc, error);
8776                         g_assert (!subc->has_references);
8777                         if (mono_error_ok (error))
8778                                 mono_gc_memmove_atomic ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
8779                 }
8780
8781                 g_free (val);
8782                 return obj;
8783         }
8784         case MONO_TYPE_SZARRAY: {
8785                 MonoArray *arr;
8786                 guint32 i, alen, basetype;
8787                 alen = read32 (p);
8788                 p += 4;
8789                 if (alen == 0xffffffff) {
8790                         *end = p;
8791                         return NULL;
8792                 }
8793                 arr = mono_array_new (mono_domain_get(), tklass, alen);
8794                 basetype = tklass->byval_arg.type;
8795                 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
8796                         basetype = mono_class_enum_basetype (tklass)->type;
8797                 switch (basetype)
8798                 {
8799                         case MONO_TYPE_U1:
8800                         case MONO_TYPE_I1:
8801                         case MONO_TYPE_BOOLEAN:
8802                                 for (i = 0; i < alen; i++) {
8803                                         MonoBoolean val = *p++;
8804                                         mono_array_set (arr, MonoBoolean, i, val);
8805                                 }
8806                                 break;
8807                         case MONO_TYPE_CHAR:
8808                         case MONO_TYPE_U2:
8809                         case MONO_TYPE_I2:
8810                                 for (i = 0; i < alen; i++) {
8811                                         guint16 val = read16 (p);
8812                                         mono_array_set (arr, guint16, i, val);
8813                                         p += 2;
8814                                 }
8815                                 break;
8816                         case MONO_TYPE_R4:
8817                         case MONO_TYPE_U4:
8818                         case MONO_TYPE_I4:
8819                                 for (i = 0; i < alen; i++) {
8820                                         guint32 val = read32 (p);
8821                                         mono_array_set (arr, guint32, i, val);
8822                                         p += 4;
8823                                 }
8824                                 break;
8825                         case MONO_TYPE_R8:
8826                                 for (i = 0; i < alen; i++) {
8827                                         double val;
8828                                         readr8 (p, &val);
8829                                         mono_array_set (arr, double, i, val);
8830                                         p += 8;
8831                                 }
8832                                 break;
8833                         case MONO_TYPE_U8:
8834                         case MONO_TYPE_I8:
8835                                 for (i = 0; i < alen; i++) {
8836                                         guint64 val = read64 (p);
8837                                         mono_array_set (arr, guint64, i, val);
8838                                         p += 8;
8839                                 }
8840                                 break;
8841                         case MONO_TYPE_CLASS:
8842                         case MONO_TYPE_OBJECT:
8843                         case MONO_TYPE_STRING:
8844                         case MONO_TYPE_SZARRAY:
8845                                 for (i = 0; i < alen; i++) {
8846                                         MonoObject *item = (MonoObject *)load_cattr_value (image, &tklass->byval_arg, p, &p, error);
8847                                         if (!mono_error_ok (error))
8848                                                 return NULL;
8849                                         mono_array_setref (arr, i, item);
8850                                 }
8851                                 break;
8852                         default:
8853                                 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8854                 }
8855                 *end=p;
8856                 return arr;
8857         }
8858         default:
8859                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8860         }
8861         return NULL;
8862 }
8863
8864 static MonoObject*
8865 create_cattr_typed_arg (MonoType *t, MonoObject *val, MonoError *error)
8866 {
8867         static MonoMethod *ctor;
8868         MonoObject *retval;
8869         void *params [2], *unboxed;
8870
8871         mono_error_init (error);
8872
8873         if (!ctor)
8874                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_typed_argument_class (), ".ctor", 2);
8875         
8876         params [0] = mono_type_get_object_checked (mono_domain_get (), t, error);
8877         return_val_if_nok (error, NULL);
8878
8879         params [1] = val;
8880         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_typed_argument_class (), error);
8881         return_val_if_nok (error, NULL);
8882         unboxed = mono_object_unbox (retval);
8883
8884         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8885         return_val_if_nok (error, NULL);
8886
8887         return retval;
8888 }
8889
8890 static MonoObject*
8891 create_cattr_named_arg (void *minfo, MonoObject *typedarg, MonoError *error)
8892 {
8893         static MonoMethod *ctor;
8894         MonoObject *retval;
8895         void *unboxed, *params [2];
8896
8897         mono_error_init (error);
8898
8899         if (!ctor)
8900                 ctor = mono_class_get_method_from_name (mono_class_get_custom_attribute_named_argument_class (), ".ctor", 2);
8901
8902         params [0] = minfo;
8903         params [1] = typedarg;
8904         retval = mono_object_new_checked (mono_domain_get (), mono_class_get_custom_attribute_named_argument_class (), error);
8905         return_val_if_nok (error, NULL);
8906
8907         unboxed = mono_object_unbox (retval);
8908
8909         mono_runtime_invoke_checked (ctor, unboxed, params, error);
8910         return_val_if_nok (error, NULL);
8911
8912         return retval;
8913 }
8914
8915 static gboolean
8916 type_is_reference (MonoType *type)
8917 {
8918         switch (type->type) {
8919         case MONO_TYPE_BOOLEAN:
8920         case MONO_TYPE_CHAR:
8921         case MONO_TYPE_U:
8922         case MONO_TYPE_I:
8923         case MONO_TYPE_U1:
8924         case MONO_TYPE_I1:
8925         case MONO_TYPE_U2:
8926         case MONO_TYPE_I2:
8927         case MONO_TYPE_U4:
8928         case MONO_TYPE_I4:
8929         case MONO_TYPE_U8:
8930         case MONO_TYPE_I8:
8931         case MONO_TYPE_R8:
8932         case MONO_TYPE_R4:
8933         case MONO_TYPE_VALUETYPE:
8934                 return FALSE;
8935         default:
8936                 return TRUE;
8937         }
8938 }
8939
8940 static void
8941 free_param_data (MonoMethodSignature *sig, void **params) {
8942         int i;
8943         for (i = 0; i < sig->param_count; ++i) {
8944                 if (!type_is_reference (sig->params [i]))
8945                         g_free (params [i]);
8946         }
8947 }
8948
8949 /*
8950  * Find the field index in the metadata FieldDef table.
8951  */
8952 static guint32
8953 find_field_index (MonoClass *klass, MonoClassField *field) {
8954         int i;
8955
8956         for (i = 0; i < klass->field.count; ++i) {
8957                 if (field == &klass->fields [i])
8958                         return klass->field.first + 1 + i;
8959         }
8960         return 0;
8961 }
8962
8963 /*
8964  * Find the property index in the metadata Property table.
8965  */
8966 static guint32
8967 find_property_index (MonoClass *klass, MonoProperty *property) {
8968         int i;
8969
8970         for (i = 0; i < klass->ext->property.count; ++i) {
8971                 if (property == &klass->ext->properties [i])
8972                         return klass->ext->property.first + 1 + i;
8973         }
8974         return 0;
8975 }
8976
8977 /*
8978  * Find the event index in the metadata Event table.
8979  */
8980 static guint32
8981 find_event_index (MonoClass *klass, MonoEvent *event) {
8982         int i;
8983
8984         for (i = 0; i < klass->ext->event.count; ++i) {
8985                 if (event == &klass->ext->events [i])
8986                         return klass->ext->event.first + 1 + i;
8987         }
8988         return 0;
8989 }
8990
8991 static MonoObject*
8992 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8993 {
8994         const char *p = (const char*)data;
8995         const char *named;
8996         guint32 i, j, num_named;
8997         MonoObject *attr;
8998         void *params_buf [32];
8999         void **params = NULL;
9000         MonoMethodSignature *sig;
9001         MonoObject *exc = NULL;
9002
9003         mono_error_init (error);
9004
9005         mono_class_init (method->klass);
9006
9007         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9008                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9009                 return NULL;
9010         }
9011
9012         if (len == 0) {
9013                 attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9014                 if (!mono_error_ok (error)) return NULL;
9015
9016                 mono_runtime_invoke_checked (method, attr, NULL, error);
9017                 if (!mono_error_ok (error))
9018                         return NULL;
9019
9020                 return attr;
9021         }
9022
9023         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9024                 return NULL;
9025
9026         /*g_print ("got attr %s\n", method->klass->name);*/
9027
9028         sig = mono_method_signature (method);
9029         if (sig->param_count < 32) {
9030                 params = params_buf;
9031                 memset (params, 0, sizeof (void*) * sig->param_count);
9032         } else {
9033                 /* Allocate using GC so it gets GC tracking */
9034                 params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
9035         }
9036
9037         /* skip prolog */
9038         p += 2;
9039         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9040                 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9041                 if (!mono_error_ok (error))
9042                         goto fail;
9043         }
9044
9045         named = p;
9046         attr = mono_object_new_checked (mono_domain_get (), method->klass, error);
9047         if (!mono_error_ok (error)) goto fail;
9048
9049         mono_runtime_try_invoke (method, attr, params, &exc, error);
9050         if (!mono_error_ok (error))
9051                 goto fail;
9052         if (exc)
9053                 goto fail;
9054
9055         num_named = read16 (named);
9056         named += 2;
9057         for (j = 0; j < num_named; j++) {
9058                 gint name_len;
9059                 char *name, named_type, data_type;
9060                 named_type = *named++;
9061                 data_type = *named++; /* type of data */
9062                 if (data_type == MONO_TYPE_SZARRAY)
9063                         data_type = *named++;
9064                 if (data_type == MONO_TYPE_ENUM) {
9065                         gint type_len;
9066                         char *type_name;
9067                         type_len = mono_metadata_decode_blob_size (named, &named);
9068                         type_name = (char *)g_malloc (type_len + 1);
9069                         memcpy (type_name, named, type_len);
9070                         type_name [type_len] = 0;
9071                         named += type_len;
9072                         /* FIXME: lookup the type and check type consistency */
9073                         g_free (type_name);
9074                 }
9075                 name_len = mono_metadata_decode_blob_size (named, &named);
9076                 name = (char *)g_malloc (name_len + 1);
9077                 memcpy (name, named, name_len);
9078                 name [name_len] = 0;
9079                 named += name_len;
9080                 if (named_type == 0x53) {
9081                         MonoClassField *field;
9082                         void *val;
9083
9084                         /* how this fail is a blackbox */
9085                         field = mono_class_get_field_from_name (mono_object_class (attr), name);
9086                         if (!field) {
9087                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a field with name %s", name);
9088                                 g_free (name);
9089                                 goto fail;
9090                         }
9091
9092                         val = load_cattr_value (image, field->type, named, &named, error);
9093                         if (!mono_error_ok (error)) {
9094                                 g_free (name);
9095                                 if (!type_is_reference (field->type))
9096                                         g_free (val);
9097                                 goto fail;
9098                         }
9099
9100                         mono_field_set_value (attr, field, val);
9101                         if (!type_is_reference (field->type))
9102                                 g_free (val);
9103                 } else if (named_type == 0x54) {
9104                         MonoProperty *prop;
9105                         void *pparams [1];
9106                         MonoType *prop_type;
9107
9108                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
9109
9110                         if (!prop) {
9111                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find a property with name %s", name);
9112                                 g_free (name);
9113                                 goto fail;
9114                         }
9115
9116                         if (!prop->set) {
9117                                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Could not find the setter for %s", name);
9118                                 g_free (name);
9119                                 goto fail;
9120                         }
9121
9122                         /* can we have more that 1 arg in a custom attr named property? */
9123                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9124                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9125
9126                         pparams [0] = load_cattr_value (image, prop_type, named, &named, error);
9127                         if (!mono_error_ok (error)) {
9128                                 g_free (name);
9129                                 if (!type_is_reference (prop_type))
9130                                         g_free (pparams [0]);
9131                                 goto fail;
9132                         }
9133
9134
9135                         mono_property_set_value (prop, attr, pparams, NULL);
9136                         if (!type_is_reference (prop_type))
9137                                 g_free (pparams [0]);
9138                 }
9139                 g_free (name);
9140         }
9141
9142         free_param_data (method->signature, params);
9143         if (params != params_buf)
9144                 mono_gc_free_fixed (params);
9145
9146         return attr;
9147
9148 fail:
9149         free_param_data (method->signature, params);
9150         if (params != params_buf)
9151                 mono_gc_free_fixed (params);
9152         if (exc)
9153                 mono_raise_exception ((MonoException*)exc);
9154         return NULL;
9155 }
9156         
9157 /*
9158  * mono_reflection_create_custom_attr_data_args:
9159  *
9160  *   Create an array of typed and named arguments from the cattr blob given by DATA.
9161  * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
9162  * NAMED_ARG_INFO will contain information about the named arguments.
9163  */
9164 void
9165 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)
9166 {
9167         MonoArray *typedargs, *namedargs;
9168         MonoClass *attrklass;
9169         MonoDomain *domain;
9170         const char *p = (const char*)data;
9171         const char *named;
9172         guint32 i, j, num_named;
9173         CattrNamedArg *arginfo = NULL;
9174
9175         *typed_args = NULL;
9176         *named_args = NULL;
9177         *named_arg_info = NULL;
9178
9179         mono_error_init (error);
9180
9181         if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
9182                 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9183                 return;
9184         }
9185
9186         mono_class_init (method->klass);
9187         
9188         domain = mono_domain_get ();
9189
9190         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
9191                 return;
9192
9193         typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
9194         
9195         /* skip prolog */
9196         p += 2;
9197         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9198                 MonoObject *obj;
9199                 void *val;
9200
9201                 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p, error);
9202                 if (!mono_error_ok (error)) {
9203                         if (!type_is_reference (mono_method_signature (method)->params [i]))
9204                                 g_free (val);
9205                         return;
9206                 }
9207
9208                 obj = (MonoObject *)(type_is_reference (mono_method_signature (method)->params [i]) ?
9209                         val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val));
9210                 mono_array_setref (typedargs, i, obj);
9211
9212                 if (!type_is_reference (mono_method_signature (method)->params [i]))
9213                         g_free (val);
9214         }
9215
9216         named = p;
9217         num_named = read16 (named);
9218         namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
9219         named += 2;
9220         attrklass = method->klass;
9221
9222         arginfo = g_new0 (CattrNamedArg, num_named);
9223         *named_arg_info = arginfo;
9224
9225         for (j = 0; j < num_named; j++) {
9226                 gint name_len;
9227                 char *name, named_type, data_type;
9228                 named_type = *named++;
9229                 data_type = *named++; /* type of data */
9230                 if (data_type == MONO_TYPE_SZARRAY)
9231                         data_type = *named++;
9232                 if (data_type == MONO_TYPE_ENUM) {
9233                         gint type_len;
9234                         char *type_name;
9235                         type_len = mono_metadata_decode_blob_size (named, &named);
9236                         if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, type_len, data + len))
9237                                 goto fail;
9238
9239                         type_name = (char *)g_malloc (type_len + 1);
9240                         memcpy (type_name, named, type_len);
9241                         type_name [type_len] = 0;
9242                         named += type_len;
9243                         /* FIXME: lookup the type and check type consistency */
9244                         g_free (type_name);
9245                 }
9246                 name_len = mono_metadata_decode_blob_size (named, &named);
9247                 if (ADDP_IS_GREATER_OR_OVF ((const guchar*)named, name_len, data + len))
9248                         goto fail;
9249                 name = (char *)g_malloc (name_len + 1);
9250                 memcpy (name, named, name_len);
9251                 name [name_len] = 0;
9252                 named += name_len;
9253                 if (named_type == 0x53) {
9254                         MonoObject *obj;
9255                         MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
9256                         void *val;
9257
9258                         if (!field) {
9259                                 g_free (name);
9260                                 goto fail;
9261                         }
9262
9263                         arginfo [j].type = field->type;
9264                         arginfo [j].field = field;
9265
9266                         val = load_cattr_value (image, field->type, named, &named, error);
9267                         if (!mono_error_ok (error)) {
9268                                 if (!type_is_reference (field->type))
9269                                         g_free (val);
9270                                 g_free (name);
9271                                 return;
9272                         }
9273
9274                         obj = (MonoObject *)(type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val));
9275                         mono_array_setref (namedargs, j, obj);
9276                         if (!type_is_reference (field->type))
9277                                 g_free (val);
9278                 } else if (named_type == 0x54) {
9279                         MonoObject *obj;
9280                         MonoType *prop_type;
9281                         MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
9282                         void *val;
9283
9284                         if (!prop || !prop->set) {
9285                                 g_free (name);
9286                                 goto fail;
9287                         }
9288
9289                         prop_type = prop->get? mono_method_signature (prop->get)->ret :
9290                              mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
9291
9292                         arginfo [j].type = prop_type;
9293                         arginfo [j].prop = prop;
9294
9295                         val = load_cattr_value (image, prop_type, named, &named, error);
9296                         if (!mono_error_ok (error)) {
9297                                 if (!type_is_reference (prop_type))
9298                                         g_free (val);
9299                                 g_free (name);
9300                                 return;
9301                         }
9302
9303                         obj = (MonoObject *)(type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val));
9304                         mono_array_setref (namedargs, j, obj);
9305                         if (!type_is_reference (prop_type))
9306                                 g_free (val);
9307                 }
9308                 g_free (name);
9309         }
9310
9311         *typed_args = typedargs;
9312         *named_args = namedargs;
9313         return;
9314 fail:
9315         mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
9316         g_free (arginfo);
9317         *named_arg_info = NULL;
9318 }
9319
9320 void
9321 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
9322 {
9323         MonoDomain *domain;
9324         MonoArray *typedargs, *namedargs;
9325         MonoImage *image;
9326         MonoMethod *method;
9327         CattrNamedArg *arginfo = NULL;
9328         MonoError error;
9329         int i;
9330
9331         mono_error_init (&error);
9332
9333         *ctor_args = NULL;
9334         *named_args = NULL;
9335
9336         if (len == 0)
9337                 return;
9338
9339         image = assembly->assembly->image;
9340         method = ref_method->method;
9341         domain = mono_object_domain (ref_method);
9342
9343         if (!mono_class_init (method->klass))
9344                 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
9345
9346         mono_reflection_create_custom_attr_data_args (image, method, (const guchar *)data, len, &typedargs, &namedargs, &arginfo, &error);
9347         if (!mono_error_ok (&error))
9348                 goto leave;
9349
9350         if (mono_loader_get_last_error ()) {
9351                 mono_error_set_from_loader_error (&error);
9352                 goto leave;
9353         }
9354
9355         if (!typedargs || !namedargs)
9356                 goto leave;
9357
9358         for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
9359                 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
9360                 MonoObject *typedarg;
9361
9362                 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj, &error);
9363                 if (!is_ok (&error))
9364                         goto leave;
9365                 mono_array_setref (typedargs, i, typedarg);
9366         }
9367
9368         for (i = 0; i < mono_array_length (namedargs); ++i) {
9369                 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
9370                 MonoObject *typedarg, *namedarg, *minfo;
9371
9372                 if (arginfo [i].prop) {
9373                         minfo = (MonoObject*)mono_property_get_object_checked (domain, NULL, arginfo [i].prop, &error);
9374                         if (!minfo)
9375                                 goto leave;
9376                 } else {
9377                         minfo = (MonoObject*)mono_field_get_object_checked (domain, NULL, arginfo [i].field, &error);
9378                         if (!mono_error_ok (&error))
9379                                 goto leave;
9380                 }
9381
9382                 typedarg = create_cattr_typed_arg (arginfo [i].type, obj, &error);
9383                 if (!is_ok (&error))
9384                         goto leave;
9385                 namedarg = create_cattr_named_arg (minfo, typedarg, &error);
9386                 if (!is_ok (&error))
9387                         goto leave;
9388
9389                 mono_array_setref (namedargs, i, namedarg);
9390         }
9391
9392         *ctor_args = typedargs;
9393         *named_args = namedargs;
9394 leave:
9395         g_free (arginfo);
9396         mono_error_raise_exception (&error);
9397
9398 }
9399
9400 static MonoObject*
9401 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr, MonoError *error)
9402 {
9403         static MonoMethod *ctor;
9404
9405         MonoDomain *domain;
9406         MonoObject *attr;
9407         void *params [4];
9408
9409         mono_error_init (error);
9410
9411         g_assert (image->assembly);
9412
9413         if (!ctor)
9414                 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
9415
9416         domain = mono_domain_get ();
9417         attr = mono_object_new_checked (domain, mono_defaults.customattribute_data_class, error);
9418         return_val_if_nok (error, NULL);
9419         params [0] = mono_method_get_object_checked (domain, cattr->ctor, NULL, error);
9420         return_val_if_nok (error, NULL);
9421         params [1] = mono_assembly_get_object_checked (domain, image->assembly, error);
9422         return_val_if_nok (error, NULL);
9423         params [2] = (gpointer)&cattr->data;
9424         params [3] = &cattr->data_size;
9425
9426         mono_runtime_invoke_checked (ctor, attr, params, error);
9427         return_val_if_nok (error, NULL);
9428         return attr;
9429 }
9430
9431 static MonoArray*
9432 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
9433 {
9434         MonoArray *result;
9435         MonoObject *attr;
9436         int i, n;
9437
9438         mono_error_init (error);
9439
9440         n = 0;
9441         for (i = 0; i < cinfo->num_attrs; ++i) {
9442                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
9443                         n ++;
9444         }
9445
9446         result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
9447         n = 0;
9448         for (i = 0; i < cinfo->num_attrs; ++i) {
9449                 if (!cinfo->attrs [i].ctor) {
9450                         /* The cattr type is not finished yet */
9451                         /* We should include the type name but cinfo doesn't contain it */
9452                         mono_error_set_type_load_name (error, NULL, NULL, "");
9453                         return NULL;
9454                 }
9455                 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
9456                         attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
9457                         if (!mono_error_ok (error))
9458                                 return result;
9459                         mono_array_setref (result, n, attr);
9460                         n ++;
9461                 }
9462         }
9463         return result;
9464 }
9465
9466 MonoArray*
9467 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
9468 {
9469         MonoError error;
9470         MonoArray *result = mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
9471         mono_error_assert_ok (&error); /*FIXME proper error handling*/
9472
9473         return result;
9474 }
9475
9476 static MonoArray*
9477 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo, MonoError *error)
9478 {
9479         MonoArray *result;
9480         MonoObject *attr;
9481         int i;
9482         
9483         mono_error_init (error);
9484         result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
9485         for (i = 0; i < cinfo->num_attrs; ++i) {
9486                 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i], error);
9487                 return_val_if_nok (error, NULL);
9488                 mono_array_setref (result, i, attr);
9489         }
9490         return result;
9491 }
9492
9493 /**
9494  * mono_custom_attrs_from_index:
9495  *
9496  * Returns: NULL if no attributes are found or if a loading error occurs.
9497  */
9498 MonoCustomAttrInfo*
9499 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
9500 {
9501         guint32 mtoken, i, len;
9502         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
9503         MonoTableInfo *ca;
9504         MonoCustomAttrInfo *ainfo;
9505         GList *tmp, *list = NULL;
9506         const char *data;
9507         MonoCustomAttrEntry* attr;
9508
9509         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
9510
9511         i = mono_metadata_custom_attrs_from_index (image, idx);
9512         if (!i)
9513                 return NULL;
9514         i --;
9515         while (i < ca->rows) {
9516                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
9517                         break;
9518                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
9519                 ++i;
9520         }
9521         len = g_list_length (list);
9522         if (!len)
9523                 return NULL;
9524         ainfo = (MonoCustomAttrInfo *)g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
9525         ainfo->num_attrs = len;
9526         ainfo->image = image;
9527         for (i = len, tmp = list; i != 0; --i, tmp = tmp->next) {
9528                 MonoError error;
9529                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
9530                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
9531                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
9532                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
9533                         mtoken |= MONO_TOKEN_METHOD_DEF;
9534                         break;
9535                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
9536                         mtoken |= MONO_TOKEN_MEMBER_REF;
9537                         break;
9538                 default:
9539                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
9540                         break;
9541                 }
9542                 attr = &ainfo->attrs [i - 1];
9543                 attr->ctor = mono_get_method_checked (image, mtoken, NULL, NULL, &error);
9544                 if (!attr->ctor) {
9545                         g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x due to %s", image->name, mtoken, mono_error_get_message (&error));
9546                         mono_loader_set_error_from_mono_error (&error);
9547                         g_list_free (list);
9548                         g_free (ainfo);
9549                         return NULL;
9550                 }
9551
9552                 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
9553                         /*FIXME raising an exception here doesn't make any sense*/
9554                         g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
9555                         g_list_free (list);
9556                         g_free (ainfo);
9557                         return NULL;
9558                 }
9559                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
9560                 attr->data_size = mono_metadata_decode_value (data, &data);
9561                 attr->data = (guchar*)data;
9562         }
9563         g_list_free (list);
9564
9565         return ainfo;
9566 }
9567
9568 MonoCustomAttrInfo*
9569 mono_custom_attrs_from_method (MonoMethod *method)
9570 {
9571         guint32 idx;
9572
9573         /*
9574          * An instantiated method has the same cattrs as the generic method definition.
9575          *
9576          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9577          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9578          */
9579         if (method->is_inflated)
9580                 method = ((MonoMethodInflated *) method)->declaring;
9581         
9582         if (method_is_dynamic (method) || image_is_dynamic (method->klass->image))
9583                 return lookup_custom_attr (method->klass->image, method);
9584
9585         if (!method->token)
9586                 /* Synthetic methods */
9587                 return NULL;
9588
9589         idx = mono_method_get_index (method);
9590         idx <<= MONO_CUSTOM_ATTR_BITS;
9591         idx |= MONO_CUSTOM_ATTR_METHODDEF;
9592         return mono_custom_attrs_from_index (method->klass->image, idx);
9593 }
9594
9595 MonoCustomAttrInfo*
9596 mono_custom_attrs_from_class (MonoClass *klass)
9597 {
9598         guint32 idx;
9599
9600         if (klass->generic_class)
9601                 klass = klass->generic_class->container_class;
9602
9603         if (image_is_dynamic (klass->image))
9604                 return lookup_custom_attr (klass->image, klass);
9605
9606         if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
9607                 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
9608                 idx <<= MONO_CUSTOM_ATTR_BITS;
9609                 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
9610         } else {
9611                 idx = mono_metadata_token_index (klass->type_token);
9612                 idx <<= MONO_CUSTOM_ATTR_BITS;
9613                 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
9614         }
9615         return mono_custom_attrs_from_index (klass->image, idx);
9616 }
9617
9618 MonoCustomAttrInfo*
9619 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
9620 {
9621         guint32 idx;
9622         
9623         if (image_is_dynamic (assembly->image))
9624                 return lookup_custom_attr (assembly->image, assembly);
9625         idx = 1; /* there is only one assembly */
9626         idx <<= MONO_CUSTOM_ATTR_BITS;
9627         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
9628         return mono_custom_attrs_from_index (assembly->image, idx);
9629 }
9630
9631 static MonoCustomAttrInfo*
9632 mono_custom_attrs_from_module (MonoImage *image)
9633 {
9634         guint32 idx;
9635         
9636         if (image_is_dynamic (image))
9637                 return lookup_custom_attr (image, image);
9638         idx = 1; /* there is only one module */
9639         idx <<= MONO_CUSTOM_ATTR_BITS;
9640         idx |= MONO_CUSTOM_ATTR_MODULE;
9641         return mono_custom_attrs_from_index (image, idx);
9642 }
9643
9644 MonoCustomAttrInfo*
9645 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
9646 {
9647         guint32 idx;
9648         
9649         if (image_is_dynamic (klass->image)) {
9650                 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
9651                 return lookup_custom_attr (klass->image, property);
9652         }
9653         idx = find_property_index (klass, property);
9654         idx <<= MONO_CUSTOM_ATTR_BITS;
9655         idx |= MONO_CUSTOM_ATTR_PROPERTY;
9656         return mono_custom_attrs_from_index (klass->image, idx);
9657 }
9658
9659 MonoCustomAttrInfo*
9660 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
9661 {
9662         guint32 idx;
9663         
9664         if (image_is_dynamic (klass->image)) {
9665                 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
9666                 return lookup_custom_attr (klass->image, event);
9667         }
9668         idx = find_event_index (klass, event);
9669         idx <<= MONO_CUSTOM_ATTR_BITS;
9670         idx |= MONO_CUSTOM_ATTR_EVENT;
9671         return mono_custom_attrs_from_index (klass->image, idx);
9672 }
9673
9674 MonoCustomAttrInfo*
9675 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
9676 {
9677         guint32 idx;
9678         if (image_is_dynamic (klass->image)) {
9679                 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
9680                 return lookup_custom_attr (klass->image, field);
9681         }
9682         idx = find_field_index (klass, field);
9683         idx <<= MONO_CUSTOM_ATTR_BITS;
9684         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
9685         return mono_custom_attrs_from_index (klass->image, idx);
9686 }
9687
9688 /**
9689  * mono_custom_attrs_from_param:
9690  * @method: handle to the method that we want to retrieve custom parameter information from
9691  * @param: parameter number, where zero represent the return value, and one is the first parameter in the method
9692  *
9693  * The result must be released with mono_custom_attrs_free().
9694  *
9695  * Returns: the custom attribute object for the specified parameter, or NULL if there are none.
9696  */
9697 MonoCustomAttrInfo*
9698 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
9699 {
9700         MonoTableInfo *ca;
9701         guint32 i, idx, method_index;
9702         guint32 param_list, param_last, param_pos, found;
9703         MonoImage *image;
9704         MonoReflectionMethodAux *aux;
9705
9706         /*
9707          * An instantiated method has the same cattrs as the generic method definition.
9708          *
9709          * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
9710          *           Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
9711          */
9712         if (method->is_inflated)
9713                 method = ((MonoMethodInflated *) method)->declaring;
9714
9715         if (image_is_dynamic (method->klass->image)) {
9716                 MonoCustomAttrInfo *res, *ainfo;
9717                 int size;
9718
9719                 aux = (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
9720                 if (!aux || !aux->param_cattr)
9721                         return NULL;
9722
9723                 /* Need to copy since it will be freed later */
9724                 ainfo = aux->param_cattr [param];
9725                 if (!ainfo)
9726                         return NULL;
9727                 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
9728                 res = (MonoCustomAttrInfo *)g_malloc0 (size);
9729                 memcpy (res, ainfo, size);
9730                 return res;
9731         }
9732
9733         image = method->klass->image;
9734         method_index = mono_method_get_index (method);
9735         if (!method_index)
9736                 return NULL;
9737         ca = &image->tables [MONO_TABLE_METHOD];
9738
9739         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
9740         if (method_index == ca->rows) {
9741                 ca = &image->tables [MONO_TABLE_PARAM];
9742                 param_last = ca->rows + 1;
9743         } else {
9744                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
9745                 ca = &image->tables [MONO_TABLE_PARAM];
9746         }
9747         found = FALSE;
9748         for (i = param_list; i < param_last; ++i) {
9749                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
9750                 if (param_pos == param) {
9751                         found = TRUE;
9752                         break;
9753                 }
9754         }
9755         if (!found)
9756                 return NULL;
9757         idx = i;
9758         idx <<= MONO_CUSTOM_ATTR_BITS;
9759         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
9760         return mono_custom_attrs_from_index (image, idx);
9761 }
9762
9763 gboolean
9764 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9765 {
9766         int i;
9767         MonoClass *klass;
9768         for (i = 0; i < ainfo->num_attrs; ++i) {
9769                 klass = ainfo->attrs [i].ctor->klass;
9770                 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
9771                         return TRUE;
9772         }
9773         return FALSE;
9774 }
9775
9776 MonoObject*
9777 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
9778 {
9779         MonoError error;
9780         MonoObject *res = mono_custom_attrs_get_attr_checked (ainfo, attr_klass, &error);
9781         g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9782         return res;
9783 }
9784
9785 MonoObject*
9786 mono_custom_attrs_get_attr_checked (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass, MonoError *error)
9787 {
9788         int i, attr_index;
9789         MonoClass *klass;
9790         MonoArray *attrs;
9791
9792         mono_error_init (error);
9793
9794         attr_index = -1;
9795         for (i = 0; i < ainfo->num_attrs; ++i) {
9796                 klass = ainfo->attrs [i].ctor->klass;
9797                 if (mono_class_has_parent (klass, attr_klass)) {
9798                         attr_index = i;
9799                         break;
9800                 }
9801         }
9802         if (attr_index == -1)
9803                 return NULL;
9804
9805         attrs = mono_custom_attrs_construct_by_type (ainfo, NULL, error);
9806         if (!mono_error_ok (error))
9807                 return NULL;
9808         return mono_array_get (attrs, MonoObject*, attr_index);
9809 }
9810
9811 /*
9812  * mono_reflection_get_custom_attrs_info:
9813  * @obj: a reflection object handle
9814  *
9815  * Return the custom attribute info for attributes defined for the
9816  * reflection handle @obj. The objects.
9817  *
9818  * FIXME this function leaks like a sieve for SRE objects.
9819  */
9820 MonoCustomAttrInfo*
9821 mono_reflection_get_custom_attrs_info (MonoObject *obj)
9822 {
9823         MonoError error;
9824         MonoCustomAttrInfo *result = mono_reflection_get_custom_attrs_info_checked (obj, &error);
9825         mono_error_assert_ok (&error);
9826         return result;
9827 }
9828
9829 /**
9830  * mono_reflection_get_custom_attrs_info_checked:
9831  * @obj: a reflection object handle
9832  * @error: set on error
9833  *
9834  * Return the custom attribute info for attributes defined for the
9835  * reflection handle @obj. The objects.
9836  *
9837  * On failure returns NULL and sets @error.
9838  *
9839  * FIXME this function leaks like a sieve for SRE objects.
9840  */
9841 MonoCustomAttrInfo*
9842 mono_reflection_get_custom_attrs_info_checked (MonoObject *obj, MonoError *error)
9843 {
9844         MonoClass *klass;
9845         MonoCustomAttrInfo *cinfo = NULL;
9846         
9847         mono_error_init (error);
9848
9849         klass = obj->vtable->klass;
9850         if (klass == mono_defaults.monotype_class) {
9851                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
9852                 klass = mono_class_from_mono_type (type);
9853                 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
9854                 cinfo = mono_custom_attrs_from_class (klass);
9855         } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
9856                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
9857                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
9858         } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
9859                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
9860                 cinfo = mono_custom_attrs_from_module (module->image);
9861         } else if (strcmp ("MonoProperty", klass->name) == 0) {
9862                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
9863                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
9864         } else if (strcmp ("MonoEvent", klass->name) == 0) {
9865                 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
9866                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
9867         } else if (strcmp ("MonoField", klass->name) == 0) {
9868                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
9869                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
9870         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
9871                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9872                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9873         } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
9874                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
9875                 cinfo = mono_custom_attrs_from_method (rmethod->method);
9876         } else if (strcmp ("ParameterInfo", klass->name) == 0 || strcmp ("MonoParameterInfo", klass->name) == 0) {
9877                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
9878                 MonoClass *member_class = mono_object_class (param->MemberImpl);
9879                 if (mono_class_is_reflection_method_or_constructor (member_class)) {
9880                         MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
9881                         cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
9882                 } else if (is_sr_mono_property (member_class)) {
9883                         MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
9884                         MonoMethod *method;
9885                         if (!(method = prop->property->get))
9886                                 method = prop->property->set;
9887                         g_assert (method);
9888
9889                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9890                 } 
9891 #ifndef DISABLE_REFLECTION_EMIT
9892                 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
9893                         MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl, error);
9894                         return_val_if_nok (error, NULL);
9895                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9896                 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
9897                         MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
9898                         MonoMethod *method = NULL;
9899                         if (is_sre_ctor_builder (mono_object_class (c->cb)))
9900                                 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
9901                         else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
9902                                 method = ((MonoReflectionMethod *)c->cb)->method;
9903                         else
9904                                 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));
9905
9906                         cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
9907                 } 
9908 #endif
9909                 else {
9910                         char *type_name = mono_type_get_full_name (member_class);
9911                         mono_error_set_generic_error (error, "System", "NotSupportedException",
9912                                                       "Custom attributes on a ParamInfo with member %s are not supported",
9913                                                       type_name);
9914                         g_free (type_name);
9915                         return NULL;
9916                 }
9917         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
9918                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
9919                 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
9920         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
9921                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
9922                 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
9923         } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
9924                 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
9925                 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
9926         } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
9927                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
9928                 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
9929         } else if (strcmp ("MethodBuilder", klass->name) == 0) {
9930                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
9931                 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
9932         } else if (strcmp ("FieldBuilder", klass->name) == 0) {
9933                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
9934                 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
9935         } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
9936                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
9937                 cinfo = mono_reflection_get_custom_attrs_info_checked ((MonoObject*)gclass->generic_type, error);
9938                 return_val_if_nok (error, NULL);
9939         } else { /* handle other types here... */
9940                 g_error ("get custom attrs not yet supported for %s", klass->name);
9941         }
9942
9943         return cinfo;
9944 }
9945
9946 /*
9947  * mono_reflection_get_custom_attrs_by_type:
9948  * @obj: a reflection object handle
9949  *
9950  * Return an array with all the custom attributes defined of the
9951  * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes 
9952  * of that type are returned. The objects are fully build. Return NULL if a loading error
9953  * occurs.
9954  */
9955 MonoArray*
9956 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
9957 {
9958         MonoArray *result;
9959         MonoCustomAttrInfo *cinfo;
9960
9961         mono_error_init (error);
9962
9963         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
9964         return_val_if_nok (error, NULL);
9965         if (cinfo) {
9966                 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
9967                 if (!result)
9968                         return NULL;
9969                 if (!cinfo->cached)
9970                         mono_custom_attrs_free (cinfo);
9971         } else {
9972                 /* FIXME add MonoError to mono_reflection_get_custom_attrs_info */
9973                 if (mono_loader_get_last_error ()) {
9974                         mono_error_set_from_loader_error (error);
9975                         return NULL;
9976                 }
9977                 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
9978         }
9979
9980         return result;
9981 }
9982
9983 /*
9984  * mono_reflection_get_custom_attrs:
9985  * @obj: a reflection object handle
9986  *
9987  * Return an array with all the custom attributes defined of the
9988  * reflection handle @obj. The objects are fully build. Return NULL if a loading error
9989  * occurs.
9990  */
9991 MonoArray*
9992 mono_reflection_get_custom_attrs (MonoObject *obj)
9993 {
9994         MonoError error;
9995
9996         return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
9997 }
9998
9999 /*
10000  * mono_reflection_get_custom_attrs_data:
10001  * @obj: a reflection obj handle
10002  *
10003  * Returns an array of System.Reflection.CustomAttributeData,
10004  * which include information about attributes reflected on
10005  * types loaded using the Reflection Only methods
10006  */
10007 MonoArray*
10008 mono_reflection_get_custom_attrs_data (MonoObject *obj)
10009 {
10010         MonoError error;
10011         MonoArray* result;
10012         result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
10013         mono_error_cleanup (&error); /* FIXME new API that doesn't swallow the error */
10014         return result;
10015 }
10016
10017 /*
10018  * mono_reflection_get_custom_attrs_data_checked:
10019  * @obj: a reflection obj handle
10020  * @error: set on error
10021  *
10022  * Returns an array of System.Reflection.CustomAttributeData,
10023  * which include information about attributes reflected on
10024  * types loaded using the Reflection Only methods
10025  */
10026 MonoArray*
10027 mono_reflection_get_custom_attrs_data_checked (MonoObject *obj, MonoError *error)
10028 {
10029         MonoArray *result;
10030         MonoCustomAttrInfo *cinfo;
10031
10032         mono_error_init (error);
10033
10034         cinfo = mono_reflection_get_custom_attrs_info_checked (obj, error);
10035         return_val_if_nok (error, NULL);
10036         if (cinfo) {
10037                 result = mono_custom_attrs_data_construct (cinfo, error);
10038                 return_val_if_nok (error, NULL);
10039                 if (!cinfo->cached)
10040                         mono_custom_attrs_free (cinfo);
10041         } else
10042                 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
10043
10044         if (mono_loader_get_last_error ())
10045                 mono_error_set_from_loader_error (error);
10046
10047         return result;
10048 }
10049
10050 static MonoReflectionType*
10051 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t, MonoError *error)
10052 {
10053         static MonoMethod *method_get_underlying_system_type = NULL;
10054         MonoReflectionType *rt;
10055         MonoMethod *usertype_method;
10056
10057         mono_error_init (error);
10058
10059         if (!method_get_underlying_system_type)
10060                 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
10061
10062         usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
10063
10064         rt = (MonoReflectionType *) mono_runtime_invoke_checked (usertype_method, t, NULL, error);
10065
10066         return rt;
10067 }
10068
10069
10070 static gboolean
10071 is_corlib_type (MonoClass *klass)
10072 {
10073         return klass->image == mono_defaults.corlib;
10074 }
10075
10076 #define check_corlib_type_cached(_class, _namespace, _name) do { \
10077         static MonoClass *cached_class; \
10078         if (cached_class) \
10079                 return cached_class == _class; \
10080         if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
10081                 cached_class = _class; \
10082                 return TRUE; \
10083         } \
10084         return FALSE; \
10085 } while (0) \
10086
10087
10088 #ifndef DISABLE_REFLECTION_EMIT
10089 static gboolean
10090 is_sre_array (MonoClass *klass)
10091 {
10092         check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
10093 }
10094
10095 static gboolean
10096 is_sre_byref (MonoClass *klass)
10097 {
10098         check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
10099 }
10100
10101 static gboolean
10102 is_sre_pointer (MonoClass *klass)
10103 {
10104         check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
10105 }
10106
10107 static gboolean
10108 is_sre_generic_instance (MonoClass *klass)
10109 {
10110         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericClass");
10111 }
10112
10113 static gboolean
10114 is_sre_type_builder (MonoClass *klass)
10115 {
10116         check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
10117 }
10118
10119 static gboolean
10120 is_sre_method_builder (MonoClass *klass)
10121 {
10122         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
10123 }
10124
10125 static gboolean
10126 is_sre_ctor_builder (MonoClass *klass)
10127 {
10128         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
10129 }
10130
10131 static gboolean
10132 is_sre_field_builder (MonoClass *klass)
10133 {
10134         check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
10135 }
10136
10137 static gboolean
10138 is_sre_method_on_tb_inst (MonoClass *klass)
10139 {
10140         check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
10141 }
10142
10143 static gboolean
10144 is_sre_ctor_on_tb_inst (MonoClass *klass)
10145 {
10146         check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
10147 }
10148
10149 MonoType*
10150 mono_reflection_type_get_handle (MonoReflectionType* ref)
10151 {
10152         MonoError error;
10153         MonoClass *klass;
10154         if (!ref)
10155                 return NULL;
10156         if (ref->type)
10157                 return ref->type;
10158
10159         if (is_usertype (ref)) {
10160                 ref = mono_reflection_type_get_underlying_system_type (ref, &error);
10161                 mono_error_raise_exception (&error); /* FIXME don't raise here */
10162                 if (ref == NULL || is_usertype (ref))
10163                         return NULL;
10164                 if (ref->type)
10165                         return ref->type;
10166         }
10167
10168         klass = mono_object_class (ref);
10169
10170         if (is_sre_array (klass)) {
10171                 MonoType *res;
10172                 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
10173                 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
10174                 g_assert (base);
10175                 if (sre_array->rank == 0) //single dimentional array
10176                         res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
10177                 else
10178                         res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
10179                 sre_array->type.type = res;
10180                 return res;
10181         } else if (is_sre_byref (klass)) {
10182                 MonoType *res;
10183                 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
10184                 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
10185                 g_assert (base);
10186                 res = &mono_class_from_mono_type (base)->this_arg;
10187                 sre_byref->type.type = res;
10188                 return res;
10189         } else if (is_sre_pointer (klass)) {
10190                 MonoType *res;
10191                 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
10192                 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
10193                 g_assert (base);
10194                 res = &mono_ptr_class_get (base)->byval_arg;
10195                 sre_pointer->type.type = res;
10196                 return res;
10197         } else if (is_sre_generic_instance (klass)) {
10198                 MonoType *res, **types;
10199                 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
10200                 int i, count;
10201
10202                 count = mono_array_length (gclass->type_arguments);
10203                 types = g_new0 (MonoType*, count);
10204                 for (i = 0; i < count; ++i) {
10205                         MonoReflectionType *t = (MonoReflectionType *)mono_array_get (gclass->type_arguments, gpointer, i);
10206                         types [i] = mono_reflection_type_get_handle (t);
10207                         if (!types[i]) {
10208                                 g_free (types);
10209                                 return NULL;
10210                         }
10211                 }
10212
10213                 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
10214                 g_free (types);
10215                 g_assert (res);
10216                 gclass->type.type = res;
10217                 return res;
10218         }
10219
10220         g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
10221         return NULL;
10222 }
10223
10224
10225
10226 void
10227 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
10228 {
10229         mono_reflection_type_get_handle (type);
10230 }
10231
10232 void
10233 mono_reflection_register_with_runtime (MonoReflectionType *type)
10234 {
10235         MonoType *res = mono_reflection_type_get_handle (type);
10236         MonoDomain *domain = mono_object_domain ((MonoObject*)type);
10237         MonoClass *klass;
10238
10239         if (!res)
10240                 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
10241
10242         klass = mono_class_from_mono_type (res);
10243
10244         mono_loader_lock (); /*same locking as mono_type_get_object_checked */
10245         mono_domain_lock (domain);
10246
10247         if (!image_is_dynamic (klass->image)) {
10248                 mono_class_setup_supertypes (klass);
10249         } else {
10250                 if (!domain->type_hash)
10251                         domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash, 
10252                                         (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, "domain reflection types table");
10253                 mono_g_hash_table_insert (domain->type_hash, res, type);
10254         }
10255         mono_domain_unlock (domain);
10256         mono_loader_unlock ();
10257 }
10258
10259 /**
10260  * LOCKING: Assumes the loader lock is held.
10261  */
10262 static MonoMethodSignature*
10263 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
10264         MonoMethodSignature *sig;
10265         int count, i;
10266
10267         count = parameters? mono_array_length (parameters): 0;
10268
10269         sig = (MonoMethodSignature *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
10270         sig->param_count = count;
10271         sig->sentinelpos = -1; /* FIXME */
10272         for (i = 0; i < count; ++i)
10273                 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
10274         return sig;
10275 }
10276
10277 /**
10278  * LOCKING: Assumes the loader lock is held.
10279  */
10280 static MonoMethodSignature*
10281 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
10282         MonoMethodSignature *sig;
10283
10284         sig = parameters_to_signature (image, ctor->parameters);
10285         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10286         sig->ret = &mono_defaults.void_class->byval_arg;
10287         return sig;
10288 }
10289
10290 /**
10291  * LOCKING: Assumes the loader lock is held.
10292  */
10293 static MonoMethodSignature*
10294 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
10295         MonoMethodSignature *sig;
10296
10297         sig = parameters_to_signature (image, method->parameters);
10298         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10299         sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
10300         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
10301         return sig;
10302 }
10303
10304 static MonoMethodSignature*
10305 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
10306         MonoMethodSignature *sig;
10307
10308         sig = parameters_to_signature (NULL, method->parameters);
10309         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
10310         sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
10311         sig->generic_param_count = 0;
10312         return sig;
10313 }
10314
10315 static void
10316 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
10317 {
10318         MonoClass *klass = mono_object_class (prop);
10319         if (strcmp (klass->name, "PropertyBuilder") == 0) {
10320                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
10321                 *name = mono_string_to_utf8 (pb->name);
10322                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
10323         } else {
10324                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
10325                 *name = g_strdup (p->property->name);
10326                 if (p->property->get)
10327                         *type = mono_method_signature (p->property->get)->ret;
10328                 else
10329                         *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
10330         }
10331 }
10332
10333 static void
10334 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
10335 {
10336         MonoClass *klass = mono_object_class (field);
10337         if (strcmp (klass->name, "FieldBuilder") == 0) {
10338                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
10339                 *name = mono_string_to_utf8 (fb->name);
10340                 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10341         } else {
10342                 MonoReflectionField *f = (MonoReflectionField *)field;
10343                 *name = g_strdup (mono_field_get_name (f->field));
10344                 *type = f->field->type;
10345         }
10346 }
10347
10348 #else /* DISABLE_REFLECTION_EMIT */
10349
10350 void
10351 mono_reflection_register_with_runtime (MonoReflectionType *type)
10352 {
10353         /* This is empty */
10354 }
10355
10356 static gboolean
10357 is_sre_type_builder (MonoClass *klass)
10358 {
10359         return FALSE;
10360 }
10361
10362 static gboolean
10363 is_sre_generic_instance (MonoClass *klass)
10364 {
10365         return FALSE;
10366 }
10367
10368 static void
10369 init_type_builder_generics (MonoObject *type)
10370 {
10371 }
10372
10373 #endif /* !DISABLE_REFLECTION_EMIT */
10374
10375
10376 static gboolean
10377 is_sr_mono_field (MonoClass *klass)
10378 {
10379         check_corlib_type_cached (klass, "System.Reflection", "MonoField");
10380 }
10381
10382 static gboolean
10383 is_sr_mono_property (MonoClass *klass)
10384 {
10385         check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
10386 }
10387
10388 static gboolean
10389 is_sr_mono_method (MonoClass *klass)
10390 {
10391         check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
10392 }
10393
10394 static gboolean
10395 is_sr_mono_cmethod (MonoClass *klass)
10396 {
10397         check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
10398 }
10399
10400 static gboolean
10401 is_sr_mono_generic_method (MonoClass *klass)
10402 {
10403         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericMethod");
10404 }
10405
10406 static gboolean
10407 is_sr_mono_generic_cmethod (MonoClass *klass)
10408 {
10409         check_corlib_type_cached (klass, "System.Reflection", "MonoGenericCMethod");
10410 }
10411
10412 gboolean
10413 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
10414 {
10415         return is_sr_mono_method (klass) || is_sr_mono_cmethod (klass) || is_sr_mono_generic_method (klass) || is_sr_mono_generic_cmethod (klass);
10416 }
10417
10418 static gboolean
10419 is_usertype (MonoReflectionType *ref)
10420 {
10421         MonoClass *klass = mono_object_class (ref);
10422         return klass->image != mono_defaults.corlib || strcmp ("TypeDelegator", klass->name) == 0;
10423 }
10424
10425 static MonoReflectionType*
10426 mono_reflection_type_resolve_user_types (MonoReflectionType *type, MonoError *error)
10427 {
10428         mono_error_init (error);
10429         if (!type || type->type)
10430                 return type;
10431
10432         if (is_usertype (type)) {
10433                 type = mono_reflection_type_get_underlying_system_type (type, error);
10434                 return_val_if_nok (error, NULL);
10435                 if (is_usertype (type)) {
10436                         mono_error_set_generic_error (error, "System", "NotSupportedException", "User defined subclasses of System.Type are not yet supported22");
10437                         return NULL;
10438                 }
10439         }
10440
10441         return type;
10442 }
10443 /*
10444  * Encode a value in a custom attribute stream of bytes.
10445  * The value to encode is either supplied as an object in argument val
10446  * (valuetypes are boxed), or as a pointer to the data in the
10447  * argument argval.
10448  * @type represents the type of the value
10449  * @buffer is the start of the buffer
10450  * @p the current position in the buffer
10451  * @buflen contains the size of the buffer and is used to return the new buffer size
10452  * if this needs to be realloced.
10453  * @retbuffer and @retp return the start and the position of the buffer
10454  */
10455 static void
10456 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
10457 {
10458         MonoTypeEnum simple_type;
10459         
10460         if ((p-buffer) + 10 >= *buflen) {
10461                 char *newbuf;
10462                 *buflen *= 2;
10463                 newbuf = (char *)g_realloc (buffer, *buflen);
10464                 p = newbuf + (p-buffer);
10465                 buffer = newbuf;
10466         }
10467         if (!argval)
10468                 argval = ((char*)arg + sizeof (MonoObject));
10469         simple_type = type->type;
10470 handle_enum:
10471         switch (simple_type) {
10472         case MONO_TYPE_BOOLEAN:
10473         case MONO_TYPE_U1:
10474         case MONO_TYPE_I1:
10475                 *p++ = *argval;
10476                 break;
10477         case MONO_TYPE_CHAR:
10478         case MONO_TYPE_U2:
10479         case MONO_TYPE_I2:
10480                 swap_with_size (p, argval, 2, 1);
10481                 p += 2;
10482                 break;
10483         case MONO_TYPE_U4:
10484         case MONO_TYPE_I4:
10485         case MONO_TYPE_R4:
10486                 swap_with_size (p, argval, 4, 1);
10487                 p += 4;
10488                 break;
10489         case MONO_TYPE_R8:
10490                 swap_with_size (p, argval, 8, 1);
10491                 p += 8;
10492                 break;
10493         case MONO_TYPE_U8:
10494         case MONO_TYPE_I8:
10495                 swap_with_size (p, argval, 8, 1);
10496                 p += 8;
10497                 break;
10498         case MONO_TYPE_VALUETYPE:
10499                 if (type->data.klass->enumtype) {
10500                         simple_type = mono_class_enum_basetype (type->data.klass)->type;
10501                         goto handle_enum;
10502                 } else {
10503                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
10504                 }
10505                 break;
10506         case MONO_TYPE_STRING: {
10507                 char *str;
10508                 guint32 slen;
10509                 if (!arg) {
10510                         *p++ = 0xFF;
10511                         break;
10512                 }
10513                 str = mono_string_to_utf8 ((MonoString*)arg);
10514                 slen = strlen (str);
10515                 if ((p-buffer) + 10 + slen >= *buflen) {
10516                         char *newbuf;
10517                         *buflen *= 2;
10518                         *buflen += slen;
10519                         newbuf = (char *)g_realloc (buffer, *buflen);
10520                         p = newbuf + (p-buffer);
10521                         buffer = newbuf;
10522                 }
10523                 mono_metadata_encode_value (slen, p, &p);
10524                 memcpy (p, str, slen);
10525                 p += slen;
10526                 g_free (str);
10527                 break;
10528         }
10529         case MONO_TYPE_CLASS: {
10530                 char *str;
10531                 guint32 slen;
10532                 if (!arg) {
10533                         *p++ = 0xFF;
10534                         break;
10535                 }
10536 handle_type:
10537                 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
10538                 slen = strlen (str);
10539                 if ((p-buffer) + 10 + slen >= *buflen) {
10540                         char *newbuf;
10541                         *buflen *= 2;
10542                         *buflen += slen;
10543                         newbuf = (char *)g_realloc (buffer, *buflen);
10544                         p = newbuf + (p-buffer);
10545                         buffer = newbuf;
10546                 }
10547                 mono_metadata_encode_value (slen, p, &p);
10548                 memcpy (p, str, slen);
10549                 p += slen;
10550                 g_free (str);
10551                 break;
10552         }
10553         case MONO_TYPE_SZARRAY: {
10554                 int len, i;
10555                 MonoClass *eclass, *arg_eclass;
10556
10557                 if (!arg) {
10558                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
10559                         break;
10560                 }
10561                 len = mono_array_length ((MonoArray*)arg);
10562                 *p++ = len & 0xff;
10563                 *p++ = (len >> 8) & 0xff;
10564                 *p++ = (len >> 16) & 0xff;
10565                 *p++ = (len >> 24) & 0xff;
10566                 *retp = p;
10567                 *retbuffer = buffer;
10568                 eclass = type->data.klass;
10569                 arg_eclass = mono_object_class (arg)->element_class;
10570
10571                 if (!eclass) {
10572                         /* Happens when we are called from the MONO_TYPE_OBJECT case below */
10573                         eclass = mono_defaults.object_class;
10574                 }
10575                 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
10576                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10577                         int elsize = mono_class_array_element_size (arg_eclass);
10578                         for (i = 0; i < len; ++i) {
10579                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
10580                                 elptr += elsize;
10581                         }
10582                 } else if (eclass->valuetype && arg_eclass->valuetype) {
10583                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
10584                         int elsize = mono_class_array_element_size (eclass);
10585                         for (i = 0; i < len; ++i) {
10586                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
10587                                 elptr += elsize;
10588                         }
10589                 } else {
10590                         for (i = 0; i < len; ++i) {
10591                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
10592                         }
10593                 }
10594                 break;
10595         }
10596         case MONO_TYPE_OBJECT: {
10597                 MonoClass *klass;
10598                 char *str;
10599                 guint32 slen;
10600
10601                 /*
10602                  * The parameter type is 'object' but the type of the actual
10603                  * argument is not. So we have to add type information to the blob
10604                  * too. This is completely undocumented in the spec.
10605                  */
10606
10607                 if (arg == NULL) {
10608                         *p++ = MONO_TYPE_STRING;        // It's same hack as MS uses
10609                         *p++ = 0xFF;
10610                         break;
10611                 }
10612                 
10613                 klass = mono_object_class (arg);
10614
10615                 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
10616                         *p++ = 0x50;
10617                         goto handle_type;
10618                 } else if (klass->enumtype) {
10619                         *p++ = 0x55;
10620                 } else if (klass == mono_defaults.string_class) {
10621                         simple_type = MONO_TYPE_STRING;
10622                         *p++ = 0x0E;
10623                         goto handle_enum;
10624                 } else if (klass->rank == 1) {
10625                         *p++ = 0x1D;
10626                         if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
10627                                 /* See Partition II, Appendix B3 */
10628                                 *p++ = 0x51;
10629                         else
10630                                 *p++ = klass->element_class->byval_arg.type;
10631                         encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
10632                         break;
10633                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
10634                         *p++ = simple_type = klass->byval_arg.type;
10635                         goto handle_enum;
10636                 } else {
10637                         g_error ("unhandled type in custom attr");
10638                 }
10639                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
10640                 slen = strlen (str);
10641                 if ((p-buffer) + 10 + slen >= *buflen) {
10642                         char *newbuf;
10643                         *buflen *= 2;
10644                         *buflen += slen;
10645                         newbuf = (char *)g_realloc (buffer, *buflen);
10646                         p = newbuf + (p-buffer);
10647                         buffer = newbuf;
10648                 }
10649                 mono_metadata_encode_value (slen, p, &p);
10650                 memcpy (p, str, slen);
10651                 p += slen;
10652                 g_free (str);
10653                 simple_type = mono_class_enum_basetype (klass)->type;
10654                 goto handle_enum;
10655         }
10656         default:
10657                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
10658         }
10659         *retp = p;
10660         *retbuffer = buffer;
10661 }
10662
10663 static void
10664 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
10665 {
10666         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10667                 char *str = type_get_qualified_name (type, NULL);
10668                 int slen = strlen (str);
10669
10670                 *p++ = 0x55;
10671                 /*
10672                  * This seems to be optional...
10673                  * *p++ = 0x80;
10674                  */
10675                 mono_metadata_encode_value (slen, p, &p);
10676                 memcpy (p, str, slen);
10677                 p += slen;
10678                 g_free (str);
10679         } else if (type->type == MONO_TYPE_OBJECT) {
10680                 *p++ = 0x51;
10681         } else if (type->type == MONO_TYPE_CLASS) {
10682                 /* it should be a type: encode_cattr_value () has the check */
10683                 *p++ = 0x50;
10684         } else {
10685                 mono_metadata_encode_value (type->type, p, &p);
10686                 if (type->type == MONO_TYPE_SZARRAY)
10687                         /* See the examples in Partition VI, Annex B */
10688                         encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
10689         }
10690
10691         *retp = p;
10692 }
10693
10694 #ifndef DISABLE_REFLECTION_EMIT
10695 static void
10696 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
10697 {
10698         int len;
10699         /* Preallocate a large enough buffer */
10700         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
10701                 char *str = type_get_qualified_name (type, NULL);
10702                 len = strlen (str);
10703                 g_free (str);
10704         } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
10705                 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
10706                 len = strlen (str);
10707                 g_free (str);
10708         } else {
10709                 len = 0;
10710         }
10711         len += strlen (name);
10712
10713         if ((p-buffer) + 20 + len >= *buflen) {
10714                 char *newbuf;
10715                 *buflen *= 2;
10716                 *buflen += len;
10717                 newbuf = (char *)g_realloc (buffer, *buflen);
10718                 p = newbuf + (p-buffer);
10719                 buffer = newbuf;
10720         }
10721
10722         encode_field_or_prop_type (type, p, &p);
10723
10724         len = strlen (name);
10725         mono_metadata_encode_value (len, p, &p);
10726         memcpy (p, name, len);
10727         p += len;
10728         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
10729         *retp = p;
10730         *retbuffer = buffer;
10731 }
10732
10733 /*
10734  * mono_reflection_get_custom_attrs_blob:
10735  * @ctor: custom attribute constructor
10736  * @ctorArgs: arguments o the constructor
10737  * @properties:
10738  * @propValues:
10739  * @fields:
10740  * @fieldValues:
10741  * 
10742  * Creates the blob of data that needs to be saved in the metadata and that represents
10743  * the custom attributed described by @ctor, @ctorArgs etc.
10744  * Returns: a Byte array representing the blob of data.
10745  */
10746 MonoArray*
10747 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
10748 {
10749         MonoArray *result;
10750         MonoMethodSignature *sig;
10751         MonoObject *arg;
10752         char *buffer, *p;
10753         guint32 buflen, i;
10754
10755         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
10756                 /* sig is freed later so allocate it in the heap */
10757                 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
10758         } else {
10759                 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
10760         }
10761
10762         g_assert (mono_array_length (ctorArgs) == sig->param_count);
10763         buflen = 256;
10764         p = buffer = (char *)g_malloc (buflen);
10765         /* write the prolog */
10766         *p++ = 1;
10767         *p++ = 0;
10768         for (i = 0; i < sig->param_count; ++i) {
10769                 arg = mono_array_get (ctorArgs, MonoObject*, i);
10770                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
10771         }
10772         i = 0;
10773         if (properties)
10774                 i += mono_array_length (properties);
10775         if (fields)
10776                 i += mono_array_length (fields);
10777         *p++ = i & 0xff;
10778         *p++ = (i >> 8) & 0xff;
10779         if (properties) {
10780                 MonoObject *prop;
10781                 for (i = 0; i < mono_array_length (properties); ++i) {
10782                         MonoType *ptype;
10783                         char *pname;
10784
10785                         prop = (MonoObject *)mono_array_get (properties, gpointer, i);
10786                         get_prop_name_and_type (prop, &pname, &ptype);
10787                         *p++ = 0x54; /* PROPERTY signature */
10788                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
10789                         g_free (pname);
10790                 }
10791         }
10792
10793         if (fields) {
10794                 MonoObject *field;
10795                 for (i = 0; i < mono_array_length (fields); ++i) {
10796                         MonoType *ftype;
10797                         char *fname;
10798
10799                         field = (MonoObject *)mono_array_get (fields, gpointer, i);
10800                         get_field_name_and_type (field, &fname, &ftype);
10801                         *p++ = 0x53; /* FIELD signature */
10802                         encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
10803                         g_free (fname);
10804                 }
10805         }
10806
10807         g_assert (p - buffer <= buflen);
10808         buflen = p - buffer;
10809         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
10810         p = mono_array_addr (result, char, 0);
10811         memcpy (p, buffer, buflen);
10812         g_free (buffer);
10813         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
10814                 g_free (sig);
10815         return result;
10816 }
10817
10818 /*
10819  * mono_reflection_setup_internal_class:
10820  * @tb: a TypeBuilder object
10821  *
10822  * Creates a MonoClass that represents the TypeBuilder.
10823  * This is a trick that lets us simplify a lot of reflection code
10824  * (and will allow us to support Build and Run assemblies easier).
10825  */
10826 void
10827 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
10828 {
10829         MonoError error;
10830         MonoClass *klass, *parent;
10831
10832         RESOLVE_TYPE (tb->parent, &error);
10833         mono_error_raise_exception (&error); /* FIXME don't raise here */
10834
10835         mono_loader_lock ();
10836
10837         if (tb->parent) {
10838                 /* check so we can compile corlib correctly */
10839                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
10840                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
10841                         parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
10842                 } else {
10843                         parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
10844                 }
10845         } else {
10846                 parent = NULL;
10847         }
10848         
10849         /* the type has already being created: it means we just have to change the parent */
10850         if (tb->type.type) {
10851                 klass = mono_class_from_mono_type (tb->type.type);
10852                 klass->parent = NULL;
10853                 /* fool mono_class_setup_parent */
10854                 klass->supertypes = NULL;
10855                 mono_class_setup_parent (klass, parent);
10856                 mono_class_setup_mono_type (klass);
10857                 mono_loader_unlock ();
10858                 return;
10859         }
10860
10861         klass = (MonoClass *)mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
10862
10863         klass->image = &tb->module->dynamic_image->image;
10864
10865         klass->inited = 1; /* we lie to the runtime */
10866         klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
10867         if (!mono_error_ok (&error))
10868                 goto failure;
10869         klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
10870         if (!mono_error_ok (&error))
10871                 goto failure;
10872         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
10873         klass->flags = tb->attrs;
10874         
10875         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
10876
10877         klass->element_class = klass;
10878
10879         if (mono_class_get_ref_info (klass) == NULL) {
10880
10881                 mono_class_set_ref_info (klass, tb);
10882
10883                 /* Put into cache so mono_class_get_checked () will find it.
10884                 Skip nested types as those should not be available on the global scope. */
10885                 if (!tb->nesting_type)
10886                         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
10887
10888                 /*
10889                 We must register all types as we cannot rely on the name_cache hashtable since we find the class
10890                 by performing a mono_class_get which does the full resolution.
10891
10892                 Working around this semantics would require us to write a lot of code for no clear advantage.
10893                 */
10894                 mono_image_append_class_to_reflection_info_set (klass);
10895         } else {
10896                 g_assert (mono_class_get_ref_info (klass) == tb);
10897         }
10898
10899         register_dyn_token (tb->module->dynamic_image, MONO_TOKEN_TYPE_DEF | tb->table_idx, (MonoObject*)tb);
10900
10901         if (parent != NULL) {
10902                 mono_class_setup_parent (klass, parent);
10903         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
10904                 const char *old_n = klass->name;
10905                 /* trick to get relative numbering right when compiling corlib */
10906                 klass->name = "BuildingObject";
10907                 mono_class_setup_parent (klass, mono_defaults.object_class);
10908                 klass->name = old_n;
10909         }
10910
10911         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
10912                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
10913                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
10914                 klass->instance_size = sizeof (MonoObject);
10915                 klass->size_inited = 1;
10916                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
10917         }
10918
10919         mono_class_setup_mono_type (klass);
10920
10921         mono_class_setup_supertypes (klass);
10922
10923         /*
10924          * FIXME: handle interfaces.
10925          */
10926
10927         tb->type.type = &klass->byval_arg;
10928
10929         if (tb->nesting_type) {
10930                 g_assert (tb->nesting_type->type);
10931                 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
10932         }
10933
10934         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
10935
10936         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
10937         
10938         mono_loader_unlock ();
10939         return;
10940
10941 failure:
10942         mono_loader_unlock ();
10943         mono_error_raise_exception (&error);
10944 }
10945
10946 /*
10947  * mono_reflection_setup_generic_class:
10948  * @tb: a TypeBuilder object
10949  *
10950  * Setup the generic class before adding the first generic parameter.
10951  */
10952 void
10953 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
10954 {
10955 }
10956
10957 /*
10958  * mono_reflection_create_generic_class:
10959  * @tb: a TypeBuilder object
10960  *
10961  * Creates the generic class after all generic parameters have been added.
10962  */
10963 void
10964 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
10965 {
10966         MonoClass *klass;
10967         int count, i;
10968
10969         klass = mono_class_from_mono_type (tb->type.type);
10970
10971         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
10972
10973         if (klass->generic_container || (count == 0))
10974                 return;
10975
10976         g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
10977
10978         klass->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
10979
10980         klass->generic_container->owner.klass = klass;
10981         klass->generic_container->type_argc = count;
10982         klass->generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
10983
10984         klass->is_generic = 1;
10985
10986         for (i = 0; i < count; i++) {
10987                 MonoReflectionGenericParam *gparam = (MonoReflectionGenericParam *)mono_array_get (tb->generic_params, gpointer, i);
10988                 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
10989                 klass->generic_container->type_params [i] = *param;
10990                 /*Make sure we are a diferent type instance */
10991                 klass->generic_container->type_params [i].param.owner = klass->generic_container;
10992                 klass->generic_container->type_params [i].info.pklass = NULL;
10993                 klass->generic_container->type_params [i].info.flags = gparam->attrs;
10994
10995                 g_assert (klass->generic_container->type_params [i].param.owner);
10996         }
10997
10998         klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
10999 }
11000
11001 /*
11002  * mono_reflection_create_internal_class:
11003  * @tb: a TypeBuilder object
11004  *
11005  * Actually create the MonoClass that is associated with the TypeBuilder.
11006  */
11007 void
11008 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11009 {
11010         MonoClass *klass;
11011
11012         klass = mono_class_from_mono_type (tb->type.type);
11013
11014         mono_loader_lock ();
11015         if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
11016                 MonoReflectionFieldBuilder *fb;
11017                 MonoClass *ec;
11018                 MonoType *enum_basetype;
11019
11020                 g_assert (tb->fields != NULL);
11021                 g_assert (mono_array_length (tb->fields) >= 1);
11022
11023                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
11024
11025                 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
11026                         mono_loader_unlock ();
11027                         return;
11028                 }
11029
11030                 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11031                 klass->element_class = mono_class_from_mono_type (enum_basetype);
11032                 if (!klass->element_class)
11033                         klass->element_class = mono_class_from_mono_type (enum_basetype);
11034
11035                 /*
11036                  * get the element_class from the current corlib.
11037                  */
11038                 ec = default_class_from_mono_type (enum_basetype);
11039                 klass->instance_size = ec->instance_size;
11040                 klass->size_inited = 1;
11041                 /* 
11042                  * this is almost safe to do with enums and it's needed to be able
11043                  * to create objects of the enum type (for use in SetConstant).
11044                  */
11045                 /* FIXME: Does this mean enums can't have method overrides ? */
11046                 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
11047         }
11048         mono_loader_unlock ();
11049 }
11050
11051 static MonoMarshalSpec*
11052 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
11053                                                                 MonoReflectionMarshal *minfo)
11054 {
11055         MonoMarshalSpec *res;
11056
11057         res = image_g_new0 (image, MonoMarshalSpec, 1);
11058         res->native = (MonoMarshalNative)minfo->type;
11059
11060         switch (minfo->type) {
11061         case MONO_NATIVE_LPARRAY:
11062                 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
11063                 if (minfo->has_size) {
11064                         res->data.array_data.param_num = minfo->param_num;
11065                         res->data.array_data.num_elem = minfo->count;
11066                         res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
11067                 }
11068                 else {
11069                         res->data.array_data.param_num = -1;
11070                         res->data.array_data.num_elem = -1;
11071                         res->data.array_data.elem_mult = -1;
11072                 }
11073                 break;
11074
11075         case MONO_NATIVE_BYVALTSTR:
11076         case MONO_NATIVE_BYVALARRAY:
11077                 res->data.array_data.num_elem = minfo->count;
11078                 break;
11079
11080         case MONO_NATIVE_CUSTOM:
11081                 if (minfo->marshaltyperef)
11082                         res->data.custom_data.custom_name =
11083                                 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
11084                 if (minfo->mcookie)
11085                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
11086                 break;
11087
11088         default:
11089                 break;
11090         }
11091
11092         return res;
11093 }
11094 #endif /* !DISABLE_REFLECTION_EMIT */
11095
11096 MonoReflectionMarshalAsAttribute*
11097 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
11098                                                         MonoMarshalSpec *spec, MonoError *error)
11099 {
11100         MonoReflectionType *rt;
11101         MonoReflectionMarshalAsAttribute *minfo;
11102         MonoType *mtype;
11103
11104         mono_error_init (error);
11105         
11106         minfo = (MonoReflectionMarshalAsAttribute*)mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error);
11107         if (!minfo)
11108                 return NULL;
11109         minfo->utype = spec->native;
11110
11111         switch (minfo->utype) {
11112         case MONO_NATIVE_LPARRAY:
11113                 minfo->array_subtype = spec->data.array_data.elem_type;
11114                 minfo->size_const = spec->data.array_data.num_elem;
11115                 if (spec->data.array_data.param_num != -1)
11116                         minfo->size_param_index = spec->data.array_data.param_num;
11117                 break;
11118
11119         case MONO_NATIVE_BYVALTSTR:
11120         case MONO_NATIVE_BYVALARRAY:
11121                 minfo->size_const = spec->data.array_data.num_elem;
11122                 break;
11123
11124         case MONO_NATIVE_CUSTOM:
11125                 if (spec->data.custom_data.custom_name) {
11126                         mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
11127                         if (mtype) {
11128                                 rt = mono_type_get_object_checked (domain, mtype, error);
11129                                 if (!rt)
11130                                         return NULL;
11131
11132                                 MONO_OBJECT_SETREF (minfo, marshal_type_ref, rt);
11133                         }
11134
11135                         MONO_OBJECT_SETREF (minfo, marshal_type, mono_string_new (domain, spec->data.custom_data.custom_name));
11136                 }
11137                 if (spec->data.custom_data.cookie)
11138                         MONO_OBJECT_SETREF (minfo, marshal_cookie, mono_string_new (domain, spec->data.custom_data.cookie));
11139                 break;
11140
11141         default:
11142                 break;
11143         }
11144
11145         return minfo;
11146 }
11147
11148 #ifndef DISABLE_REFLECTION_EMIT
11149 static MonoMethod*
11150 reflection_methodbuilder_to_mono_method (MonoClass *klass,
11151                                          ReflectionMethodBuilder *rmb,
11152                                          MonoMethodSignature *sig)
11153 {
11154         MonoError error;
11155         MonoMethod *m;
11156         MonoMethodWrapper *wrapperm;
11157         MonoMarshalSpec **specs;
11158         MonoReflectionMethodAux *method_aux;
11159         MonoImage *image;
11160         gboolean dynamic;
11161         int i;
11162
11163         mono_error_init (&error);
11164         /*
11165          * Methods created using a MethodBuilder should have their memory allocated
11166          * inside the image mempool, while dynamic methods should have their memory
11167          * malloc'd.
11168          */
11169         dynamic = rmb->refs != NULL;
11170         image = dynamic ? NULL : klass->image;
11171
11172         if (!dynamic)
11173                 g_assert (!klass->generic_class);
11174
11175         mono_loader_lock ();
11176
11177         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
11178                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
11179                 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
11180         else
11181                 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
11182
11183         wrapperm = (MonoMethodWrapper*)m;
11184
11185         m->dynamic = dynamic;
11186         m->slot = -1;
11187         m->flags = rmb->attrs;
11188         m->iflags = rmb->iattrs;
11189         m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
11190         m->klass = klass;
11191         m->signature = sig;
11192         m->sre_method = TRUE;
11193         m->skip_visibility = rmb->skip_visibility;
11194         if (rmb->table_idx)
11195                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
11196
11197         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
11198                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
11199                         m->string_ctor = 1;
11200
11201                 m->signature->pinvoke = 1;
11202         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
11203                 m->signature->pinvoke = 1;
11204
11205                 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11206
11207                 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
11208                 g_assert (mono_error_ok (&error));
11209                 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
11210                 g_assert (mono_error_ok (&error));
11211                 
11212                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
11213
11214                 if (image_is_dynamic (klass->image))
11215                         g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11216
11217                 mono_loader_unlock ();
11218
11219                 return m;
11220         } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
11221                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
11222                 MonoMethodHeader *header;
11223                 guint32 code_size;
11224                 gint32 max_stack, i;
11225                 gint32 num_locals = 0;
11226                 gint32 num_clauses = 0;
11227                 guint8 *code;
11228
11229                 if (rmb->ilgen) {
11230                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
11231                         code_size = rmb->ilgen->code_len;
11232                         max_stack = rmb->ilgen->max_stack;
11233                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
11234                         if (rmb->ilgen->ex_handlers)
11235                                 num_clauses = method_count_clauses (rmb->ilgen);
11236                 } else {
11237                         if (rmb->code) {
11238                                 code = mono_array_addr (rmb->code, guint8, 0);
11239                                 code_size = mono_array_length (rmb->code);
11240                                 /* we probably need to run a verifier on the code... */
11241                                 max_stack = 8; 
11242                         }
11243                         else {
11244                                 code = NULL;
11245                                 code_size = 0;
11246                                 max_stack = 8;
11247                         }
11248                 }
11249
11250                 header = (MonoMethodHeader *)image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
11251                 header->code_size = code_size;
11252                 header->code = (const unsigned char *)image_g_malloc (image, code_size);
11253                 memcpy ((char*)header->code, code, code_size);
11254                 header->max_stack = max_stack;
11255                 header->init_locals = rmb->init_locals;
11256                 header->num_locals = num_locals;
11257
11258                 for (i = 0; i < num_locals; ++i) {
11259                         MonoReflectionLocalBuilder *lb = 
11260                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
11261
11262                         header->locals [i] = image_g_new0 (image, MonoType, 1);
11263                         memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
11264                 }
11265
11266                 header->num_clauses = num_clauses;
11267                 if (num_clauses) {
11268                         header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
11269                                  rmb->ilgen, num_clauses);
11270                 }
11271
11272                 wrapperm->header = header;
11273         }
11274
11275         if (rmb->generic_params) {
11276                 int count = mono_array_length (rmb->generic_params);
11277                 MonoGenericContainer *container = rmb->generic_container;
11278
11279                 g_assert (container);
11280
11281                 container->type_argc = count;
11282                 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
11283                 container->owner.method = m;
11284                 container->is_anonymous = FALSE; // Method is now known, container is no longer anonymous
11285
11286                 m->is_generic = TRUE;
11287                 mono_method_set_generic_container (m, container);
11288
11289                 for (i = 0; i < count; i++) {
11290                         MonoReflectionGenericParam *gp =
11291                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
11292                         MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
11293                         container->type_params [i] = *param;
11294                 }
11295
11296                 /*
11297                  * The method signature might have pointers to generic parameters that belong to other methods.
11298                  * This is a valid SRE case, but the resulting method signature must be encoded using the proper
11299                  * generic parameters.
11300                  */
11301                 for (i = 0; i < m->signature->param_count; ++i) {
11302                         MonoType *t = m->signature->params [i];
11303                         if (t->type == MONO_TYPE_MVAR) {
11304                                 MonoGenericParam *gparam =  t->data.generic_param;
11305                                 if (gparam->num < count) {
11306                                         m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
11307                                         m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
11308                                 }
11309
11310                         }
11311                 }
11312
11313                 if (klass->generic_container) {
11314                         container->parent = klass->generic_container;
11315                         container->context.class_inst = klass->generic_container->context.class_inst;
11316                 }
11317                 container->context.method_inst = mono_get_shared_generic_inst (container);
11318         }
11319
11320         if (rmb->refs) {
11321                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
11322                 int i;
11323                 void **data;
11324
11325                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
11326
11327                 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
11328                 data [0] = GUINT_TO_POINTER (rmb->nrefs);
11329                 for (i = 0; i < rmb->nrefs; ++i)
11330                         data [i + 1] = rmb->refs [i];
11331         }
11332
11333         method_aux = NULL;
11334
11335         /* Parameter info */
11336         if (rmb->pinfo) {
11337                 if (!method_aux)
11338                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11339                 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
11340                 for (i = 0; i <= m->signature->param_count; ++i) {
11341                         MonoReflectionParamBuilder *pb;
11342                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11343                                 if ((i > 0) && (pb->attrs)) {
11344                                         /* Make a copy since it might point to a shared type structure */
11345                                         m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
11346                                         m->signature->params [i - 1]->attrs = pb->attrs;
11347                                 }
11348
11349                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
11350                                         MonoDynamicImage *assembly;
11351                                         guint32 idx, len;
11352                                         MonoTypeEnum def_type;
11353                                         char *p;
11354                                         const char *p2;
11355
11356                                         if (!method_aux->param_defaults) {
11357                                                 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
11358                                                 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
11359                                         }
11360                                         assembly = (MonoDynamicImage*)klass->image;
11361                                         idx = encode_constant (assembly, pb->def_value, &def_type);
11362                                         /* Copy the data from the blob since it might get realloc-ed */
11363                                         p = assembly->blob.data + idx;
11364                                         len = mono_metadata_decode_blob_size (p, &p2);
11365                                         len += p2 - p;
11366                                         method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
11367                                         method_aux->param_default_types [i] = def_type;
11368                                         memcpy ((gpointer)method_aux->param_defaults [i], p, len);
11369                                 }
11370
11371                                 if (pb->name) {
11372                                         method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
11373                                         g_assert (mono_error_ok (&error));
11374                                 }
11375                                 if (pb->cattrs) {
11376                                         if (!method_aux->param_cattr)
11377                                                 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
11378                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
11379                                 }
11380                         }
11381                 }
11382         }
11383
11384         /* Parameter marshalling */
11385         specs = NULL;
11386         if (rmb->pinfo)         
11387                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
11388                         MonoReflectionParamBuilder *pb;
11389                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
11390                                 if (pb->marshal_info) {
11391                                         if (specs == NULL)
11392                                                 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
11393                                         specs [pb->position] = 
11394                                                 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
11395                                 }
11396                         }
11397                 }
11398         if (specs != NULL) {
11399                 if (!method_aux)
11400                         method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
11401                 method_aux->param_marshall = specs;
11402         }
11403
11404         if (image_is_dynamic (klass->image) && method_aux)
11405                 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
11406
11407         mono_loader_unlock ();
11408
11409         return m;
11410 }       
11411
11412 static MonoMethod*
11413 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
11414 {
11415         ReflectionMethodBuilder rmb;
11416         MonoMethodSignature *sig;
11417
11418         mono_loader_lock ();
11419         sig = ctor_builder_to_signature (klass->image, mb);
11420         mono_loader_unlock ();
11421
11422         if (!reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
11423                 return NULL;
11424
11425         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11426         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11427
11428         /* If we are in a generic class, we might be called multiple times from inflate_method */
11429         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11430                 /* ilgen is no longer needed */
11431                 mb->ilgen = NULL;
11432         }
11433
11434         return mb->mhandle;
11435 }
11436
11437 static MonoMethod*
11438 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb, MonoError *error)
11439 {
11440         ReflectionMethodBuilder rmb;
11441         MonoMethodSignature *sig;
11442
11443         mono_error_init (error);
11444
11445         mono_loader_lock ();
11446         sig = method_builder_to_signature (klass->image, mb);
11447         mono_loader_unlock ();
11448
11449         if (!reflection_methodbuilder_from_method_builder (&rmb, mb, error))
11450                 return NULL;
11451
11452         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11453         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
11454
11455         /* If we are in a generic class, we might be called multiple times from inflate_method */
11456         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
11457                 /* ilgen is no longer needed */
11458                 mb->ilgen = NULL;
11459         }
11460         return mb->mhandle;
11461 }
11462
11463 static MonoClassField*
11464 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
11465 {
11466         MonoClassField *field;
11467         MonoType *custom;
11468         MonoError error;
11469
11470         field = g_new0 (MonoClassField, 1);
11471
11472         field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
11473         g_assert (mono_error_ok (&error));
11474         if (fb->attrs || fb->modreq || fb->modopt) {
11475                 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
11476                 field->type->attrs = fb->attrs;
11477
11478                 g_assert (image_is_dynamic (klass->image));
11479                 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
11480                 g_free (field->type);
11481                 field->type = mono_metadata_type_dup (klass->image, custom);
11482                 g_free (custom);
11483         } else {
11484                 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
11485         }
11486         if (fb->offset != -1)
11487                 field->offset = fb->offset;
11488         field->parent = klass;
11489         mono_save_custom_attrs (klass->image, field, fb->cattrs);
11490
11491         // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
11492
11493         return field;
11494 }
11495 #endif
11496
11497 MonoType*
11498 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
11499 {
11500         MonoClass *klass;
11501         MonoReflectionTypeBuilder *tb = NULL;
11502         gboolean is_dynamic = FALSE;
11503         MonoClass *geninst;
11504
11505         mono_loader_lock ();
11506
11507         if (is_sre_type_builder (mono_object_class (type))) {
11508                 tb = (MonoReflectionTypeBuilder *) type;
11509
11510                 is_dynamic = TRUE;
11511         } else if (is_sre_generic_instance (mono_object_class (type))) {
11512                 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
11513                 MonoReflectionType *gtd = rgi->generic_type;
11514
11515                 if (is_sre_type_builder (mono_object_class (gtd))) {
11516                         tb = (MonoReflectionTypeBuilder *)gtd;
11517                         is_dynamic = TRUE;
11518                 }
11519         }
11520
11521         /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
11522         if (tb && tb->generic_container)
11523                 mono_reflection_create_generic_class (tb);
11524
11525         klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11526         if (!klass->generic_container) {
11527                 mono_loader_unlock ();
11528                 return NULL;
11529         }
11530
11531         if (klass->wastypebuilder) {
11532                 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
11533
11534                 is_dynamic = TRUE;
11535         }
11536
11537         mono_loader_unlock ();
11538
11539         geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
11540
11541         return &geninst->byval_arg;
11542 }
11543
11544 MonoClass*
11545 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
11546 {
11547         MonoGenericClass *gclass;
11548         MonoGenericInst *inst;
11549
11550         g_assert (klass->generic_container);
11551
11552         inst = mono_metadata_get_generic_inst (type_argc, types);
11553         gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
11554
11555         return mono_generic_class_get_class (gclass);
11556 }
11557
11558 MonoReflectionMethod*
11559 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
11560 {
11561         MonoError error;
11562         MonoClass *klass;
11563         MonoMethod *method, *inflated;
11564         MonoMethodInflated *imethod;
11565         MonoGenericContext tmp_context;
11566         MonoGenericInst *ginst;
11567         MonoType **type_argv;
11568         int count, i;
11569
11570         /*FIXME but this no longer should happen*/
11571         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
11572 #ifndef DISABLE_REFLECTION_EMIT
11573                 MonoReflectionMethodBuilder *mb = NULL;
11574                 MonoReflectionTypeBuilder *tb;
11575                 MonoClass *klass;
11576
11577                 mb = (MonoReflectionMethodBuilder *) rmethod;
11578                 tb = (MonoReflectionTypeBuilder *) mb->type;
11579                 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11580
11581                 method = methodbuilder_to_mono_method (klass, mb, &error);
11582                 if (!method)
11583                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11584 #else
11585                 g_assert_not_reached ();
11586                 method = NULL;
11587 #endif
11588         } else {
11589                 method = rmethod->method;
11590         }
11591
11592         klass = method->klass;
11593
11594         if (method->is_inflated)
11595                 method = ((MonoMethodInflated *) method)->declaring;
11596
11597         count = mono_method_signature (method)->generic_param_count;
11598         if (count != mono_array_length (types))
11599                 return NULL;
11600
11601         type_argv = g_new0 (MonoType *, count);
11602         for (i = 0; i < count; i++) {
11603                 MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
11604                 type_argv [i] = mono_reflection_type_get_handle (garg);
11605         }
11606         ginst = mono_metadata_get_generic_inst (count, type_argv);
11607         g_free (type_argv);
11608
11609         tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
11610         tmp_context.method_inst = ginst;
11611
11612         inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, &error);
11613         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11614         imethod = (MonoMethodInflated *) inflated;
11615
11616         /*FIXME but I think this is no longer necessary*/
11617         if (image_is_dynamic (method->klass->image)) {
11618                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11619                 /*
11620                  * This table maps metadata structures representing inflated methods/fields
11621                  * to the reflection objects representing their generic definitions.
11622                  */
11623                 mono_image_lock ((MonoImage*)image);
11624                 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
11625                 mono_image_unlock ((MonoImage*)image);
11626         }
11627
11628         if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
11629                 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
11630         
11631         MonoReflectionMethod *ret = mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, &error);
11632         mono_error_raise_exception (&error); /* FIXME don't raise here */
11633         return ret;
11634 }
11635
11636 #ifndef DISABLE_REFLECTION_EMIT
11637
11638 static MonoMethod *
11639 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
11640 {
11641         MonoMethodInflated *imethod;
11642         MonoGenericContext *context;
11643         int i;
11644
11645         /*
11646          * With generic code sharing the klass might not be inflated.
11647          * This can happen because classes inflated with their own
11648          * type arguments are "normalized" to the uninflated class.
11649          */
11650         if (!klass->generic_class)
11651                 return method;
11652
11653         context = mono_class_get_context (klass);
11654
11655         if (klass->method.count && klass->methods) {
11656                 /* Find the already created inflated method */
11657                 for (i = 0; i < klass->method.count; ++i) {
11658                         g_assert (klass->methods [i]->is_inflated);
11659                         if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
11660                                 break;
11661                 }
11662                 g_assert (i < klass->method.count);
11663                 imethod = (MonoMethodInflated*)klass->methods [i];
11664         } else {
11665                 MonoError error;
11666                 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full_checked (method, klass, context, &error);
11667                 mono_error_assert_ok (&error);
11668         }
11669
11670         if (method->is_generic && image_is_dynamic (method->klass->image)) {
11671                 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
11672
11673                 mono_image_lock ((MonoImage*)image);
11674                 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
11675                 mono_image_unlock ((MonoImage*)image);
11676         }
11677         return (MonoMethod *) imethod;
11678 }
11679
11680 static MonoMethod *
11681 inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error)
11682 {
11683         MonoMethod *method;
11684         MonoClass *gklass;
11685
11686         mono_error_init (error);
11687
11688         MonoClass *type_class = mono_object_class (type);
11689
11690         if (is_sre_generic_instance (type_class)) {
11691                 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
11692                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
11693         } else if (is_sre_type_builder (type_class)) {
11694                 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
11695         } else if (type->type) {
11696                 gklass = mono_class_from_mono_type (type->type);
11697                 gklass = mono_class_get_generic_type_definition (gklass);
11698         } else {
11699                 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
11700         }
11701
11702         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
11703                 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
11704                         method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
11705                 else {
11706                         method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj, error);
11707                         if (!method)
11708                                 return NULL;
11709                 }
11710         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder")) {
11711                 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj, error);
11712                 if (!method)
11713                         return NULL;
11714         } else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
11715                 method = ((MonoReflectionMethod *) obj)->method;
11716         else {
11717                 method = NULL; /* prevent compiler warning */
11718                 g_error ("can't handle type %s", obj->vtable->klass->name);
11719         }
11720
11721         return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
11722 }
11723
11724 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
11725 void
11726 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
11727 {
11728         MonoGenericClass *gclass;
11729         MonoDynamicGenericClass *dgclass;
11730         MonoClass *klass, *gklass;
11731         MonoType *gtype;
11732         int i;
11733
11734         gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
11735         klass = mono_class_from_mono_type (gtype);
11736         g_assert (gtype->type == MONO_TYPE_GENERICINST);
11737         gclass = gtype->data.generic_class;
11738
11739         if (!gclass->is_dynamic)
11740                 return;
11741
11742         dgclass = (MonoDynamicGenericClass *) gclass;
11743
11744         if (dgclass->initialized)
11745                 return;
11746
11747         gklass = gclass->container_class;
11748         mono_class_init (gklass);
11749
11750         dgclass->count_fields = fields ? mono_array_length (fields) : 0;
11751
11752         dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
11753         dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
11754         dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
11755
11756         for (i = 0; i < dgclass->count_fields; i++) {
11757                 MonoObject *obj = (MonoObject *)mono_array_get (fields, gpointer, i);
11758                 MonoClassField *field, *inflated_field = NULL;
11759
11760                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
11761                         inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
11762                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
11763                         field = ((MonoReflectionField *) obj)->field;
11764                 else {
11765                         field = NULL; /* prevent compiler warning */
11766                         g_assert_not_reached ();
11767                 }
11768
11769                 dgclass->fields [i] = *field;
11770                 dgclass->fields [i].parent = klass;
11771                 dgclass->fields [i].type = mono_class_inflate_generic_type (
11772                         field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
11773                 dgclass->field_generic_types [i] = field->type;
11774                 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i], MONO_ROOT_SOURCE_REFLECTION, "dynamic generic class field object");
11775                 dgclass->field_objects [i] = obj;
11776
11777                 if (inflated_field) {
11778                         g_free (inflated_field);
11779                 } else {
11780                         dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
11781                 }
11782         }
11783
11784         dgclass->initialized = TRUE;
11785 }
11786
11787 void
11788 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
11789 {
11790         MonoDynamicGenericClass *dgclass;
11791         int i;
11792
11793         g_assert (gclass->is_dynamic);
11794
11795         dgclass = (MonoDynamicGenericClass *)gclass;
11796
11797         for (i = 0; i < dgclass->count_fields; ++i) {
11798                 MonoClassField *field = dgclass->fields + i;
11799                 mono_metadata_free_type (field->type);
11800                 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
11801         }
11802 }
11803
11804 static void
11805 fix_partial_generic_class (MonoClass *klass)
11806 {
11807         MonoClass *gklass = klass->generic_class->container_class;
11808         MonoDynamicGenericClass *dgclass;
11809         int i;
11810
11811         if (klass->wastypebuilder)
11812                 return;
11813
11814         dgclass = (MonoDynamicGenericClass *)  klass->generic_class;
11815         if (klass->parent != gklass->parent) {
11816                 MonoError error;
11817                 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
11818                 if (mono_error_ok (&error)) {
11819                         MonoClass *parent = mono_class_from_mono_type (parent_type);
11820                         mono_metadata_free_type (parent_type);
11821                         if (parent != klass->parent) {
11822                                 /*fool mono_class_setup_parent*/
11823                                 klass->supertypes = NULL;
11824                                 mono_class_setup_parent (klass, parent);
11825                         }
11826                 } else {
11827                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11828                         mono_error_cleanup (&error);
11829                         if (gklass->wastypebuilder)
11830                                 klass->wastypebuilder = TRUE;
11831                         return;
11832                 }
11833         }
11834
11835         if (!dgclass->initialized)
11836                 return;
11837
11838         if (klass->method.count != gklass->method.count) {
11839                 klass->method.count = gklass->method.count;
11840                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
11841
11842                 for (i = 0; i < klass->method.count; i++) {
11843                         MonoError error;
11844                         klass->methods [i] = mono_class_inflate_generic_method_full_checked (
11845                                 gklass->methods [i], klass, mono_class_get_context (klass), &error);
11846                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
11847                 }
11848         }
11849
11850         if (klass->interface_count && klass->interface_count != gklass->interface_count) {
11851                 klass->interface_count = gklass->interface_count;
11852                 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
11853                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11854
11855                 for (i = 0; i < gklass->interface_count; ++i) {
11856                         MonoError error;
11857                         MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
11858                         klass->interfaces [i] = mono_class_from_mono_type (iface_type);
11859                         mono_metadata_free_type (iface_type);
11860
11861                         ensure_runtime_vtable (klass->interfaces [i], &error);
11862                         mono_error_raise_exception (&error); /* FIXME don't raise here */
11863                 }
11864                 klass->interfaces_inited = 1;
11865         }
11866
11867         if (klass->field.count != gklass->field.count) {
11868                 klass->field.count = gklass->field.count;
11869                 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
11870
11871                 for (i = 0; i < klass->field.count; i++) {
11872                         klass->fields [i] = gklass->fields [i];
11873                         klass->fields [i].parent = klass;
11874                         klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
11875                 }
11876         }
11877
11878         /*We can only finish with this klass once it's parent has as well*/
11879         if (gklass->wastypebuilder)
11880                 klass->wastypebuilder = TRUE;
11881         return;
11882 }
11883
11884 /**
11885  * ensure_generic_class_runtime_vtable:
11886  * @klass a generic class
11887  * @error set on error
11888  *
11889  * Ensures that the generic container of @klass has a vtable and
11890  * returns TRUE on success.  On error returns FALSE and sets @error.
11891  */
11892 static gboolean
11893 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
11894 {
11895         MonoClass *gklass = klass->generic_class->container_class;
11896
11897         mono_error_init (error);
11898
11899         if (!ensure_runtime_vtable (gklass, error))
11900                 return FALSE;
11901
11902         fix_partial_generic_class (klass);
11903
11904         return TRUE;
11905 }
11906
11907 /**
11908  * ensure_runtime_vtable:
11909  * @klass the class
11910  * @error set on error
11911  *
11912  * Ensures that @klass has a vtable and returns TRUE on success. On
11913  * error returns FALSE and sets @error.
11914  */
11915 static gboolean
11916 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
11917 {
11918         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
11919         int i, num, j;
11920
11921         mono_error_init (error);
11922
11923         if (!image_is_dynamic (klass->image) || (!tb && !klass->generic_class) || klass->wastypebuilder)
11924                 return TRUE;
11925         if (klass->parent)
11926                 if (!ensure_runtime_vtable (klass->parent, error))
11927                         return FALSE;
11928
11929         if (tb) {
11930                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11931                 num += tb->num_methods;
11932                 klass->method.count = num;
11933                 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
11934                 num = tb->ctors? mono_array_length (tb->ctors): 0;
11935                 for (i = 0; i < num; ++i) {
11936                         MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
11937                         if (!ctor)
11938                                 return FALSE;
11939                         klass->methods [i] = ctor;
11940                 }
11941                 num = tb->num_methods;
11942                 j = i;
11943                 for (i = 0; i < num; ++i) {
11944                         MonoMethod *meth = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error);
11945                         if (!meth)
11946                                 return FALSE;
11947                         klass->methods [j++] = meth;
11948                 }
11949         
11950                 if (tb->interfaces) {
11951                         klass->interface_count = mono_array_length (tb->interfaces);
11952                         klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
11953                         for (i = 0; i < klass->interface_count; ++i) {
11954                                 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
11955                                 klass->interfaces [i] = mono_class_from_mono_type (iface);
11956                                 if (!ensure_runtime_vtable (klass->interfaces [i], error))
11957                                         return FALSE;
11958                         }
11959                         klass->interfaces_inited = 1;
11960                 }
11961         } else if (klass->generic_class){
11962                 if (!ensure_generic_class_runtime_vtable (klass, error))
11963                         return FALSE;
11964         }
11965
11966         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
11967                 int slot_num = 0;
11968                 for (i = 0; i < klass->method.count; ++i) {
11969                         MonoMethod *im = klass->methods [i];
11970                         if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
11971                                 im->slot = slot_num++;
11972                 }
11973                 
11974                 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
11975                 mono_class_setup_interface_offsets (klass);
11976                 mono_class_setup_interface_id (klass);
11977         }
11978
11979         /*
11980          * The generic vtable is needed even if image->run is not set since some
11981          * runtime code like ves_icall_Type_GetMethodsByName depends on 
11982          * method->slot being defined.
11983          */
11984
11985         /* 
11986          * tb->methods could not be freed since it is used for determining 
11987          * overrides during dynamic vtable construction.
11988          */
11989
11990         return TRUE;
11991 }
11992
11993 static MonoMethod*
11994 mono_reflection_method_get_handle (MonoObject *method)
11995 {
11996         MonoError error;
11997         MonoClass *klass = mono_object_class (method);
11998         if (is_sr_mono_method (klass) || is_sr_mono_generic_method (klass)) {
11999                 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
12000                 return sr_method->method;
12001         }
12002         if (is_sre_method_builder (klass)) {
12003                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
12004                 return mb->mhandle;
12005         }
12006         if (is_sre_method_on_tb_inst (klass)) {
12007                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
12008                 MonoMethod *result;
12009                 /*FIXME move this to a proper method and unify with resolve_object*/
12010                 if (m->method_args) {
12011                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
12012                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12013                 } else {
12014                         MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
12015                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
12016                         MonoMethod *mono_method;
12017
12018                         if (is_sre_method_builder (mono_object_class (m->mb)))
12019                                 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
12020                         else if (is_sr_mono_method (mono_object_class (m->mb)))
12021                                 mono_method = ((MonoReflectionMethod *)m->mb)->method;
12022                         else
12023                                 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)));
12024
12025                         result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
12026                 }
12027                 return result;
12028         }
12029
12030         g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
12031         return NULL;
12032 }
12033
12034 void
12035 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12036 {
12037         MonoReflectionTypeBuilder *tb;
12038         int i, j, onum;
12039         MonoReflectionMethod *m;
12040
12041         *overrides = NULL;
12042         *num_overrides = 0;
12043
12044         g_assert (image_is_dynamic (klass->image));
12045
12046         if (!mono_class_get_ref_info (klass))
12047                 return;
12048
12049         g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
12050
12051         tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
12052
12053         onum = 0;
12054         if (tb->methods) {
12055                 for (i = 0; i < tb->num_methods; ++i) {
12056                         MonoReflectionMethodBuilder *mb = 
12057                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12058                         if (mb->override_methods)
12059                                 onum += mono_array_length (mb->override_methods);
12060                 }
12061         }
12062
12063         if (onum) {
12064                 *overrides = g_new0 (MonoMethod*, onum * 2);
12065
12066                 onum = 0;
12067                 for (i = 0; i < tb->num_methods; ++i) {
12068                         MonoReflectionMethodBuilder *mb = 
12069                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
12070                         if (mb->override_methods) {
12071                                 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
12072                                         m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
12073
12074                                         (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m);
12075                                         (*overrides) [onum * 2 + 1] = mb->mhandle;
12076
12077                                         g_assert (mb->mhandle);
12078
12079                                         onum ++;
12080                                 }
12081                         }
12082                 }
12083         }
12084
12085         *num_overrides = onum;
12086 }
12087
12088 static void
12089 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
12090 {
12091         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12092         MonoReflectionFieldBuilder *fb;
12093         MonoClassField *field;
12094         MonoImage *image = klass->image;
12095         const char *p, *p2;
12096         int i;
12097         guint32 len, idx, real_size = 0;
12098
12099         klass->field.count = tb->num_fields;
12100         klass->field.first = 0;
12101
12102         mono_error_init (error);
12103
12104         if (tb->class_size) {
12105                 if ((tb->packing_size & 0xffffff00) != 0) {
12106                         char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, tb->packing_size);
12107                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
12108                         return;
12109                 }
12110                 klass->packing_size = tb->packing_size;
12111                 real_size = klass->instance_size + tb->class_size;
12112         }
12113
12114         if (!klass->field.count) {
12115                 klass->instance_size = MAX (klass->instance_size, real_size);
12116                 return;
12117         }
12118         
12119         klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
12120         mono_class_alloc_ext (klass);
12121         klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
12122         /*
12123         This is, guess what, a hack.
12124         The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
12125         On the static path no field class is resolved, only types are built. This is the right thing to do
12126         but we suck.
12127         Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
12128         */
12129         klass->size_inited = 1;
12130
12131         for (i = 0; i < klass->field.count; ++i) {
12132                 MonoArray *rva_data;
12133                 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12134                 field = &klass->fields [i];
12135                 field->name = mono_string_to_utf8_image (image, fb->name, error);
12136                 if (!mono_error_ok (error))
12137                         return;
12138                 if (fb->attrs) {
12139                         field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
12140                         field->type->attrs = fb->attrs;
12141                 } else {
12142                         field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
12143                 }
12144
12145                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
12146                         char *base = mono_array_addr (rva_data, char, 0);
12147                         size_t size = mono_array_length (rva_data);
12148                         char *data = (char *)mono_image_alloc (klass->image, size);
12149                         memcpy (data, base, size);
12150                         klass->ext->field_def_values [i].data = data;
12151                 }
12152                 if (fb->offset != -1)
12153                         field->offset = fb->offset;
12154                 field->parent = klass;
12155                 fb->handle = field;
12156                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
12157
12158                 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
12159                         klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
12160                 }
12161                 if (fb->def_value) {
12162                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12163                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
12164                         idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
12165                         /* Copy the data from the blob since it might get realloc-ed */
12166                         p = assembly->blob.data + idx;
12167                         len = mono_metadata_decode_blob_size (p, &p2);
12168                         len += p2 - p;
12169                         klass->ext->field_def_values [i].data = (const char *)mono_image_alloc (image, len);
12170                         memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
12171                 }
12172         }
12173
12174         klass->instance_size = MAX (klass->instance_size, real_size);
12175         mono_class_layout_fields (klass);
12176 }
12177
12178 static void
12179 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
12180 {
12181         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12182         MonoReflectionPropertyBuilder *pb;
12183         MonoImage *image = klass->image;
12184         MonoProperty *properties;
12185         int i;
12186
12187         mono_error_init (error);
12188
12189         if (!klass->ext)
12190                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12191
12192         klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
12193         klass->ext->property.first = 0;
12194
12195         properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
12196         klass->ext->properties = properties;
12197         for (i = 0; i < klass->ext->property.count; ++i) {
12198                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
12199                 properties [i].parent = klass;
12200                 properties [i].attrs = pb->attrs;
12201                 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
12202                 if (!mono_error_ok (error))
12203                         return;
12204                 if (pb->get_method)
12205                         properties [i].get = pb->get_method->mhandle;
12206                 if (pb->set_method)
12207                         properties [i].set = pb->set_method->mhandle;
12208
12209                 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
12210                 if (pb->def_value) {
12211                         guint32 len, idx;
12212                         const char *p, *p2;
12213                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
12214                         if (!klass->ext->prop_def_values)
12215                                 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
12216                         properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
12217                         idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
12218                         /* Copy the data from the blob since it might get realloc-ed */
12219                         p = assembly->blob.data + idx;
12220                         len = mono_metadata_decode_blob_size (p, &p2);
12221                         len += p2 - p;
12222                         klass->ext->prop_def_values [i].data = (const char *)mono_image_alloc (image, len);
12223                         memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
12224                 }
12225         }
12226 }
12227
12228 MonoReflectionEvent *
12229 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12230 {
12231         MonoError error;
12232         MonoEvent *event = g_new0 (MonoEvent, 1);
12233         MonoClass *klass;
12234
12235         klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12236
12237         event->parent = klass;
12238         event->attrs = eb->attrs;
12239         event->name = mono_string_to_utf8 (eb->name);
12240         if (eb->add_method)
12241                 event->add = eb->add_method->mhandle;
12242         if (eb->remove_method)
12243                 event->remove = eb->remove_method->mhandle;
12244         if (eb->raise_method)
12245                 event->raise = eb->raise_method->mhandle;
12246
12247 #ifndef MONO_SMALL_CONFIG
12248         if (eb->other_methods) {
12249                 int j;
12250                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
12251                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12252                         MonoReflectionMethodBuilder *mb = 
12253                                 mono_array_get (eb->other_methods,
12254                                                 MonoReflectionMethodBuilder*, j);
12255                         event->other [j] = mb->mhandle;
12256                 }
12257         }
12258 #endif
12259
12260         MonoReflectionEvent *ev_obj = mono_event_get_object_checked (mono_object_domain (tb), klass, event, &error);
12261         mono_error_raise_exception (&error); /* FIXME don't raise here */
12262         return ev_obj;
12263 }
12264
12265 static void
12266 typebuilder_setup_events (MonoClass *klass, MonoError *error)
12267 {
12268         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12269         MonoReflectionEventBuilder *eb;
12270         MonoImage *image = klass->image;
12271         MonoEvent *events;
12272         int i;
12273
12274         mono_error_init (error);
12275
12276         if (!klass->ext)
12277                 klass->ext = image_g_new0 (image, MonoClassExt, 1);
12278
12279         klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
12280         klass->ext->event.first = 0;
12281
12282         events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
12283         klass->ext->events = events;
12284         for (i = 0; i < klass->ext->event.count; ++i) {
12285                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
12286                 events [i].parent = klass;
12287                 events [i].attrs = eb->attrs;
12288                 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
12289                 if (!mono_error_ok (error))
12290                         return;
12291                 if (eb->add_method)
12292                         events [i].add = eb->add_method->mhandle;
12293                 if (eb->remove_method)
12294                         events [i].remove = eb->remove_method->mhandle;
12295                 if (eb->raise_method)
12296                         events [i].raise = eb->raise_method->mhandle;
12297
12298 #ifndef MONO_SMALL_CONFIG
12299                 if (eb->other_methods) {
12300                         int j;
12301                         events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
12302                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
12303                                 MonoReflectionMethodBuilder *mb = 
12304                                         mono_array_get (eb->other_methods,
12305                                                                         MonoReflectionMethodBuilder*, j);
12306                                 events [i].other [j] = mb->mhandle;
12307                         }
12308                 }
12309 #endif
12310                 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
12311         }
12312 }
12313
12314 static gboolean
12315 remove_instantiations_of_and_ensure_contents (gpointer key,
12316                                                   gpointer value,
12317                                                   gpointer user_data)
12318 {
12319         MonoType *type = (MonoType*)key;
12320         MonoClass *klass = (MonoClass*)user_data;
12321
12322         if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
12323                 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
12324                 return TRUE;
12325         } else
12326                 return FALSE;
12327 }
12328
12329 static void
12330 check_array_for_usertypes (MonoArray *arr, MonoError *error)
12331 {
12332         mono_error_init (error);
12333         int i;
12334
12335         if (!arr)
12336                 return;
12337
12338         for (i = 0; i < mono_array_length (arr); ++i) {
12339                 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i, error);
12340                 if (!mono_error_ok (error))
12341                         break;
12342         }
12343 }
12344
12345 MonoReflectionType*
12346 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12347 {
12348         MonoError error;
12349         MonoClass *klass;
12350         MonoDomain* domain;
12351         MonoReflectionType* res;
12352         int i, j;
12353
12354         domain = mono_object_domain (tb);
12355         klass = mono_class_from_mono_type (tb->type.type);
12356
12357         /*
12358          * Check for user defined Type subclasses.
12359          */
12360         RESOLVE_TYPE (tb->parent, &error);
12361         mono_error_raise_exception (&error); /* FIXME don't raise here */
12362         check_array_for_usertypes (tb->interfaces, &error);
12363         mono_error_raise_exception (&error); /*FIXME don't raise here */
12364         if (tb->fields) {
12365                 for (i = 0; i < mono_array_length (tb->fields); ++i) {
12366                         MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
12367                         if (fb) {
12368                                 RESOLVE_TYPE (fb->type, &error);
12369                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12370                                 check_array_for_usertypes (fb->modreq, &error);
12371                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12372                                 check_array_for_usertypes (fb->modopt, &error);
12373                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12374                                 if (fb->marshal_info && fb->marshal_info->marshaltyperef) {
12375                                         RESOLVE_TYPE (fb->marshal_info->marshaltyperef, &error);
12376                                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12377                                 }
12378                         }
12379                 }
12380         }
12381         if (tb->methods) {
12382                 for (i = 0; i < mono_array_length (tb->methods); ++i) {
12383                         MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)mono_array_get (tb->methods, gpointer, i);
12384                         if (mb) {
12385                                 RESOLVE_TYPE (mb->rtype, &error);
12386                                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12387                                 check_array_for_usertypes (mb->return_modreq, &error);
12388                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12389                                 check_array_for_usertypes (mb->return_modopt, &error);
12390                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12391                                 check_array_for_usertypes (mb->parameters, &error);
12392                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12393                                 if (mb->param_modreq)
12394                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12395                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12396                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12397                                         }
12398                                 if (mb->param_modopt)
12399                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12400                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12401                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12402                                         }
12403                         }
12404                 }
12405         }
12406         if (tb->ctors) {
12407                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
12408                         MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)mono_array_get (tb->ctors, gpointer, i);
12409                         if (mb) {
12410                                 check_array_for_usertypes (mb->parameters, &error);
12411                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12412                                 if (mb->param_modreq)
12413                                         for (j = 0; j < mono_array_length (mb->param_modreq); ++j) {
12414                                                 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j), &error);
12415                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12416                                         }
12417                                 if (mb->param_modopt)
12418                                         for (j = 0; j < mono_array_length (mb->param_modopt); ++j) {
12419                                                 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j), &error);
12420                                                 mono_error_raise_exception (&error); /*FIXME don't raise here */
12421                                         }
12422                         }
12423                 }
12424         }
12425
12426         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
12427
12428         /* 
12429          * we need to lock the domain because the lock will be taken inside
12430          * So, we need to keep the locking order correct.
12431          */
12432         mono_loader_lock ();
12433         mono_domain_lock (domain);
12434         if (klass->wastypebuilder) {
12435                 mono_domain_unlock (domain);
12436                 mono_loader_unlock ();
12437
12438                 res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12439                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12440
12441                 return res;
12442         }
12443         /*
12444          * Fields to set in klass:
12445          * the various flags: delegate/unicode/contextbound etc.
12446          */
12447         klass->flags = tb->attrs;
12448         klass->has_cctor = 1;
12449         klass->has_finalize = 1;
12450         klass->has_finalize_inited = 1;
12451
12452         mono_class_setup_parent (klass, klass->parent);
12453         /* fool mono_class_setup_supertypes */
12454         klass->supertypes = NULL;
12455         mono_class_setup_supertypes (klass);
12456         mono_class_setup_mono_type (klass);
12457
12458 #if 0
12459         if (!((MonoDynamicImage*)klass->image)->run) {
12460                 if (klass->generic_container) {
12461                         /* FIXME: The code below can't handle generic classes */
12462                         klass->wastypebuilder = TRUE;
12463                         mono_loader_unlock ();
12464                         mono_domain_unlock (domain);
12465
12466                         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12467                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12468
12469                         return res;
12470                 }
12471         }
12472 #endif
12473
12474         /* enums are done right away */
12475         if (!klass->enumtype)
12476                 if (!ensure_runtime_vtable (klass, &error))
12477                         goto failure;
12478
12479         if (tb->subtypes) {
12480                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
12481                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
12482                         mono_class_alloc_ext (klass);
12483                         klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)subtb)));
12484                 }
12485         }
12486
12487         klass->nested_classes_inited = TRUE;
12488
12489         /* fields and object layout */
12490         if (klass->parent) {
12491                 if (!klass->parent->size_inited)
12492                         mono_class_init (klass->parent);
12493                 klass->instance_size = klass->parent->instance_size;
12494                 klass->sizes.class_size = 0;
12495                 klass->min_align = klass->parent->min_align;
12496                 /* if the type has no fields we won't call the field_setup
12497                  * routine which sets up klass->has_references.
12498                  */
12499                 klass->has_references |= klass->parent->has_references;
12500         } else {
12501                 klass->instance_size = sizeof (MonoObject);
12502                 klass->min_align = 1;
12503         }
12504
12505         /* FIXME: handle packing_size and instance_size */
12506         typebuilder_setup_fields (klass, &error);
12507         if (!mono_error_ok (&error))
12508                 goto failure;
12509         typebuilder_setup_properties (klass, &error);
12510         if (!mono_error_ok (&error))
12511                 goto failure;
12512
12513         typebuilder_setup_events (klass, &error);
12514         if (!mono_error_ok (&error))
12515                 goto failure;
12516
12517         klass->wastypebuilder = TRUE;
12518
12519         /* 
12520          * If we are a generic TypeBuilder, there might be instantiations in the type cache
12521          * which have type System.Reflection.MonoGenericClass, but after the type is created, 
12522          * we want to return normal System.MonoType objects, so clear these out from the cache.
12523          *
12524          * Together with this we must ensure the contents of all instances to match the created type.
12525          */
12526         if (domain->type_hash && klass->generic_container)
12527                 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
12528
12529         mono_domain_unlock (domain);
12530         mono_loader_unlock ();
12531
12532         if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
12533                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12534                 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
12535         }
12536
12537         res = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
12538         mono_error_raise_exception (&error); /* FIXME don't raise here */
12539
12540         g_assert (res != (MonoReflectionType*)tb);
12541
12542         return res;
12543
12544 failure:
12545         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
12546         klass->wastypebuilder = TRUE;
12547         mono_domain_unlock (domain);
12548         mono_loader_unlock ();
12549         mono_error_raise_exception (&error);
12550         return NULL;
12551 }
12552
12553 void
12554 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12555 {
12556         MonoGenericParamFull *param;
12557         MonoImage *image;
12558         MonoClass *pklass;
12559         MonoError error;
12560
12561         image = &gparam->tbuilder->module->dynamic_image->image;
12562
12563         param = mono_image_new0 (image, MonoGenericParamFull, 1);
12564
12565         param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
12566         g_assert (mono_error_ok (&error));
12567         param->param.num = gparam->index;
12568
12569         if (gparam->mbuilder) {
12570                 if (!gparam->mbuilder->generic_container) {
12571                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
12572                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
12573                         gparam->mbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12574                         gparam->mbuilder->generic_container->is_method = TRUE;
12575                         /* 
12576                          * Cannot set owner.method, since the MonoMethod is not created yet.
12577                          * Set the image field instead, so type_in_image () works.
12578                          */
12579                         gparam->mbuilder->generic_container->is_anonymous = TRUE;
12580                         gparam->mbuilder->generic_container->owner.image = klass->image;
12581                 }
12582                 param->param.owner = gparam->mbuilder->generic_container;
12583         } else if (gparam->tbuilder) {
12584                 if (!gparam->tbuilder->generic_container) {
12585                         MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
12586                         gparam->tbuilder->generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
12587                         gparam->tbuilder->generic_container->owner.klass = klass;
12588                 }
12589                 param->param.owner = gparam->tbuilder->generic_container;
12590         }
12591
12592         pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
12593
12594         gparam->type.type = &pklass->byval_arg;
12595
12596         mono_class_set_ref_info (pklass, gparam);
12597         mono_image_append_class_to_reflection_info_set (pklass);
12598 }
12599
12600 MonoArray *
12601 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12602 {
12603         MonoError error;
12604         MonoReflectionModuleBuilder *module = sig->module;
12605         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
12606         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12607         guint32 buflen, i;
12608         MonoArray *result;
12609         SigBuffer buf;
12610
12611         check_array_for_usertypes (sig->arguments, &error);
12612         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12613
12614         sigbuffer_init (&buf, 32);
12615
12616         sigbuffer_add_value (&buf, 0x07);
12617         sigbuffer_add_value (&buf, na);
12618         if (assembly != NULL){
12619                 for (i = 0; i < na; ++i) {
12620                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12621                         encode_reflection_type (assembly, type, &buf);
12622                 }
12623         }
12624
12625         buflen = buf.p - buf.buf;
12626         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12627         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12628         sigbuffer_free (&buf);
12629
12630         return result;
12631 }
12632
12633 MonoArray *
12634 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12635 {
12636         MonoError error;
12637         MonoDynamicImage *assembly = sig->module->dynamic_image;
12638         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
12639         guint32 buflen, i;
12640         MonoArray *result;
12641         SigBuffer buf;
12642
12643         check_array_for_usertypes (sig->arguments, &error);
12644         mono_error_raise_exception (&error); /* FIXME: don't raise here */
12645
12646         sigbuffer_init (&buf, 32);
12647
12648         sigbuffer_add_value (&buf, 0x06);
12649         for (i = 0; i < na; ++i) {
12650                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
12651                 encode_reflection_type (assembly, type, &buf);
12652         }
12653
12654         buflen = buf.p - buf.buf;
12655         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
12656         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
12657         sigbuffer_free (&buf);
12658
12659         return result;
12660 }
12661
12662 typedef struct {
12663         MonoMethod *handle;
12664         MonoDomain *domain;
12665 } DynamicMethodReleaseData;
12666
12667 /*
12668  * The runtime automatically clean up those after finalization.
12669 */      
12670 static MonoReferenceQueue *dynamic_method_queue;
12671
12672 static void
12673 free_dynamic_method (void *dynamic_method)
12674 {
12675         DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
12676         MonoDomain *domain = data->domain;
12677         MonoMethod *method = data->handle;
12678         guint32 dis_link;
12679
12680         mono_domain_lock (domain);
12681         dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
12682         g_hash_table_remove (domain->method_to_dyn_method, method);
12683         mono_domain_unlock (domain);
12684         g_assert (dis_link);
12685         mono_gchandle_free (dis_link);
12686
12687         mono_runtime_free_method (domain, method);
12688         g_free (data);
12689 }
12690
12691 void 
12692 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12693 {
12694         MonoReferenceQueue *queue;
12695         MonoMethod *handle;
12696         DynamicMethodReleaseData *release_data;
12697         ReflectionMethodBuilder rmb;
12698         MonoMethodSignature *sig;
12699         MonoClass *klass;
12700         MonoDomain *domain;
12701         GSList *l;
12702         int i;
12703
12704         if (mono_runtime_is_shutting_down ())
12705                 mono_raise_exception (mono_get_exception_invalid_operation (""));
12706
12707         if (!(queue = dynamic_method_queue)) {
12708                 mono_loader_lock ();
12709                 if (!(queue = dynamic_method_queue))
12710                         queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
12711                 mono_loader_unlock ();
12712         }
12713
12714         sig = dynamic_method_to_signature (mb);
12715
12716         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
12717
12718         /*
12719          * Resolve references.
12720          */
12721         /* 
12722          * Every second entry in the refs array is reserved for storing handle_class,
12723          * which is needed by the ldtoken implementation in the JIT.
12724          */
12725         rmb.nrefs = mb->nrefs;
12726         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
12727         for (i = 0; i < mb->nrefs; i += 2) {
12728                 MonoClass *handle_class;
12729                 gpointer ref;
12730                 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
12731
12732                 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
12733                         MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
12734                         /*
12735                          * The referenced DynamicMethod should already be created by the managed
12736                          * code, except in the case of circular references. In that case, we store
12737                          * method in the refs array, and fix it up later when the referenced 
12738                          * DynamicMethod is created.
12739                          */
12740                         if (method->mhandle) {
12741                                 ref = method->mhandle;
12742                         } else {
12743                                 /* FIXME: GC object stored in unmanaged memory */
12744                                 ref = method;
12745
12746                                 /* FIXME: GC object stored in unmanaged memory */
12747                                 method->referenced_by = g_slist_append (method->referenced_by, mb);
12748                         }
12749                         handle_class = mono_defaults.methodhandle_class;
12750                 } else {
12751                         MonoException *ex = NULL;
12752                         ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
12753                         if (!ref)
12754                                 ex = mono_get_exception_type_load (NULL, NULL);
12755                         else if (mono_security_core_clr_enabled ())
12756                                 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
12757
12758                         if (ex) {
12759                                 g_free (rmb.refs);
12760                                 mono_raise_exception (ex);
12761                                 return;
12762                         }
12763                 }
12764
12765                 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
12766                 rmb.refs [i + 1] = handle_class;
12767         }               
12768
12769         klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
12770
12771         mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
12772         release_data = g_new (DynamicMethodReleaseData, 1);
12773         release_data->handle = handle;
12774         release_data->domain = mono_object_get_domain ((MonoObject*)mb);
12775         if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
12776                 g_free (release_data);
12777
12778         /* Fix up refs entries pointing at us */
12779         for (l = mb->referenced_by; l; l = l->next) {
12780                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
12781                 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
12782                 gpointer *data;
12783                 
12784                 g_assert (method->mhandle);
12785
12786                 data = (gpointer*)wrapper->method_data;
12787                 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
12788                         if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
12789                                 data [i + 1] = mb->mhandle;
12790                 }
12791         }
12792         g_slist_free (mb->referenced_by);
12793
12794         g_free (rmb.refs);
12795
12796         /* ilgen is no longer needed */
12797         mb->ilgen = NULL;
12798
12799         domain = mono_domain_get ();
12800         mono_domain_lock (domain);
12801         if (!domain->method_to_dyn_method)
12802                 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
12803         g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
12804         mono_domain_unlock (domain);
12805 }
12806
12807 #endif /* DISABLE_REFLECTION_EMIT */
12808
12809 /**
12810  * 
12811  * mono_reflection_is_valid_dynamic_token:
12812  * 
12813  * Returns TRUE if token is valid.
12814  * 
12815  */
12816 gboolean
12817 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
12818 {
12819         return lookup_dyn_token (image, token) != NULL;
12820 }
12821
12822 MonoMethodSignature *
12823 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
12824 {
12825         MonoMethodSignature *sig;
12826         g_assert (image_is_dynamic (image));
12827
12828         mono_error_init (error);
12829
12830         sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
12831         if (sig)
12832                 return sig;
12833
12834         return mono_method_signature_checked (method, error);
12835 }
12836
12837 #ifndef DISABLE_REFLECTION_EMIT
12838
12839 /**
12840  * mono_reflection_lookup_dynamic_token:
12841  *
12842  * Finish the Builder object pointed to by TOKEN and return the corresponding
12843  * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by 
12844  * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
12845  * mapping table.
12846  *
12847  * LOCKING: Take the loader lock
12848  */
12849 gpointer
12850 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12851 {
12852         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
12853         MonoObject *obj;
12854         MonoClass *klass;
12855
12856         obj = lookup_dyn_token (assembly, token);
12857         if (!obj) {
12858                 if (valid_token)
12859                         g_error ("Could not find required dynamic token 0x%08x", token);
12860                 else
12861                         return NULL;
12862         }
12863
12864         if (!handle_class)
12865                 handle_class = &klass;
12866         return resolve_object (image, obj, handle_class, context);
12867 }
12868
12869 /*
12870  * ensure_complete_type:
12871  *
12872  *   Ensure that KLASS is completed if it is a dynamic type, or references
12873  * dynamic types.
12874  */
12875 static void
12876 ensure_complete_type (MonoClass *klass)
12877 {
12878         MonoError error;
12879
12880         if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
12881                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
12882
12883                 mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12884                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12885
12886                 // Asserting here could break a lot of code
12887                 //g_assert (klass->wastypebuilder);
12888         }
12889
12890         if (klass->generic_class) {
12891                 MonoGenericInst *inst = klass->generic_class->context.class_inst;
12892                 int i;
12893
12894                 for (i = 0; i < inst->type_argc; ++i) {
12895                         ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
12896                 }
12897         }
12898 }
12899
12900 static gpointer
12901 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
12902 {
12903         MonoError error;
12904         gpointer result = NULL;
12905
12906         if (strcmp (obj->vtable->klass->name, "String") == 0) {
12907                 result = mono_string_intern_checked ((MonoString*)obj, &error);
12908                 mono_error_raise_exception (&error); /* FIXME don't raise here */
12909                 *handle_class = mono_defaults.string_class;
12910                 g_assert (result);
12911         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
12912                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
12913                 MonoClass *mc = mono_class_from_mono_type (type);
12914                 if (!mono_class_init (mc))
12915                         mono_raise_exception (mono_class_get_exception_for_failure (mc));
12916
12917                 if (context) {
12918                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
12919                         result = mono_class_from_mono_type (inflated);
12920                         mono_metadata_free_type (inflated);
12921                 } else {
12922                         result = mono_class_from_mono_type (type);
12923                 }
12924                 *handle_class = mono_defaults.typehandle_class;
12925                 g_assert (result);
12926         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
12927                    strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
12928                    strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
12929                    strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
12930                 result = ((MonoReflectionMethod*)obj)->method;
12931                 if (context) {
12932                         MonoError error;
12933                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12934                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12935                 }
12936                 *handle_class = mono_defaults.methodhandle_class;
12937                 g_assert (result);
12938         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
12939                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
12940                 result = mb->mhandle;
12941                 if (!result) {
12942                         /* Type is not yet created */
12943                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
12944
12945                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12946                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12947
12948                         /*
12949                          * Hopefully this has been filled in by calling CreateType() on the
12950                          * TypeBuilder.
12951                          */
12952                         /*
12953                          * TODO: This won't work if the application finishes another 
12954                          * TypeBuilder instance instead of this one.
12955                          */
12956                         result = mb->mhandle;
12957                 }
12958                 if (context) {
12959                         MonoError error;
12960                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12961                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12962                 }
12963                 *handle_class = mono_defaults.methodhandle_class;
12964         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
12965                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
12966
12967                 result = cb->mhandle;
12968                 if (!result) {
12969                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
12970
12971                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
12972                         mono_error_raise_exception (&error); /* FIXME don't raise here */
12973                         result = cb->mhandle;
12974                 }
12975                 if (context) {
12976                         MonoError error;
12977                         result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
12978                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
12979                 }
12980                 *handle_class = mono_defaults.methodhandle_class;
12981         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
12982                 MonoClassField *field = ((MonoReflectionField*)obj)->field;
12983
12984                 ensure_complete_type (field->parent);
12985                 if (context) {
12986                         MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
12987                         MonoClass *klass = mono_class_from_mono_type (inflated);
12988                         MonoClassField *inflated_field;
12989                         gpointer iter = NULL;
12990                         mono_metadata_free_type (inflated);
12991                         while ((inflated_field = mono_class_get_fields (klass, &iter))) {
12992                                 if (!strcmp (field->name, inflated_field->name))
12993                                         break;
12994                         }
12995                         g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
12996                         result = inflated_field;
12997                 } else {
12998                         result = field;
12999                 }
13000                 *handle_class = mono_defaults.fieldhandle_class;
13001                 g_assert (result);
13002         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
13003                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
13004                 result = fb->handle;
13005
13006                 if (!result) {
13007                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
13008
13009                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13010                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13011                         result = fb->handle;
13012                 }
13013
13014                 if (fb->handle && fb->handle->parent->generic_container) {
13015                         MonoClass *klass = fb->handle->parent;
13016                         MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
13017                         MonoClass *inflated = mono_class_from_mono_type (type);
13018
13019                         result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
13020                         g_assert (result);
13021                         mono_metadata_free_type (type);
13022                 }
13023                 *handle_class = mono_defaults.fieldhandle_class;
13024         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
13025                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
13026                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb); 
13027                 MonoClass *klass;
13028
13029                 klass = type->data.klass;
13030                 if (klass->wastypebuilder) {
13031                         /* Already created */
13032                         result = klass;
13033                 }
13034                 else {
13035                         mono_domain_try_type_resolve_checked (mono_domain_get (), NULL, (MonoObject*)tb, &error);
13036                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13037                         result = type->data.klass;
13038                         g_assert (result);
13039                 }
13040                 *handle_class = mono_defaults.typehandle_class;
13041         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
13042                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
13043                 MonoMethodSignature *sig;
13044                 int nargs, i;
13045
13046                 if (helper->arguments)
13047                         nargs = mono_array_length (helper->arguments);
13048                 else
13049                         nargs = 0;
13050
13051                 sig = mono_metadata_signature_alloc (image, nargs);
13052                 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
13053                 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
13054
13055                 if (helper->unmanaged_call_conv) { /* unmanaged */
13056                         sig->call_convention = helper->unmanaged_call_conv - 1;
13057                         sig->pinvoke = TRUE;
13058                 } else if (helper->call_conv & 0x02) {
13059                         sig->call_convention = MONO_CALL_VARARG;
13060                 } else {
13061                         sig->call_convention = MONO_CALL_DEFAULT;
13062                 }
13063
13064                 sig->param_count = nargs;
13065                 /* TODO: Copy type ? */
13066                 sig->ret = helper->return_type->type;
13067                 for (i = 0; i < nargs; ++i)
13068                         sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
13069
13070                 result = sig;
13071                 *handle_class = NULL;
13072         } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
13073                 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
13074                 /* Already created by the managed code */
13075                 g_assert (method->mhandle);
13076                 result = method->mhandle;
13077                 *handle_class = mono_defaults.methodhandle_class;
13078         } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
13079                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13080                 type = mono_class_inflate_generic_type (type, context);
13081                 result = mono_class_from_mono_type (type);
13082                 *handle_class = mono_defaults.typehandle_class;
13083                 g_assert (result);
13084                 mono_metadata_free_type (type);
13085         } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
13086                 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
13087                 type = mono_class_inflate_generic_type (type, context);
13088                 result = mono_class_from_mono_type (type);
13089                 *handle_class = mono_defaults.typehandle_class;
13090                 g_assert (result);
13091                 mono_metadata_free_type (type);
13092         } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
13093                 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
13094                 MonoClass *inflated;
13095                 MonoType *type;
13096                 MonoClassField *field;
13097
13098                 if (is_sre_field_builder (mono_object_class (f->fb)))
13099                         field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
13100                 else if (is_sr_mono_field (mono_object_class (f->fb)))
13101                         field = ((MonoReflectionField*)f->fb)->field;
13102                 else
13103                         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)));
13104
13105                 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
13106                 inflated = mono_class_from_mono_type (type);
13107
13108                 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
13109                 ensure_complete_type (field->parent);
13110                 g_assert (result);
13111                 mono_metadata_free_type (type);
13112                 *handle_class = mono_defaults.fieldhandle_class;
13113         } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
13114                 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
13115                 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
13116                 MonoClass *inflated_klass = mono_class_from_mono_type (type);
13117                 MonoMethod *method;
13118
13119                 if (is_sre_ctor_builder (mono_object_class (c->cb)))
13120                         method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
13121                 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
13122                         method = ((MonoReflectionMethod *)c->cb)->method;
13123                 else
13124                         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)));
13125
13126                 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
13127                 *handle_class = mono_defaults.methodhandle_class;
13128                 mono_metadata_free_type (type);
13129         } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
13130                 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
13131                 if (m->method_args) {
13132                         result = mono_reflection_method_on_tb_inst_get_handle (m, &error);
13133                         mono_error_raise_exception (&error); /* FIXME don't raise here */
13134                         if (context) {
13135                                 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, &error);
13136                                 mono_error_assert_ok (&error);
13137                         }
13138                 } else {
13139                         MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
13140                         MonoClass *inflated_klass = mono_class_from_mono_type (type);
13141                         MonoMethod *method;
13142
13143                         if (is_sre_method_builder (mono_object_class (m->mb)))
13144                                 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
13145                         else if (is_sr_mono_method (mono_object_class (m->mb)))
13146                                 method = ((MonoReflectionMethod *)m->mb)->method;
13147                         else
13148                                 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)));
13149
13150                         result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
13151                         mono_metadata_free_type (type);
13152                 }
13153                 *handle_class = mono_defaults.methodhandle_class;
13154         } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
13155                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
13156                 MonoType *mtype;
13157                 MonoClass *klass;
13158                 MonoMethod *method;
13159                 gpointer iter;
13160                 char *name;
13161
13162                 mtype = mono_reflection_type_get_handle (m->parent);
13163                 klass = mono_class_from_mono_type (mtype);
13164
13165                 /* Find the method */
13166
13167                 name = mono_string_to_utf8 (m->name);
13168                 iter = NULL;
13169                 while ((method = mono_class_get_methods (klass, &iter))) {
13170                         if (!strcmp (method->name, name))
13171                                 break;
13172                 }
13173                 g_free (name);
13174
13175                 // FIXME:
13176                 g_assert (method);
13177                 // FIXME: Check parameters/return value etc. match
13178
13179                 result = method;
13180                 *handle_class = mono_defaults.methodhandle_class;
13181         } else if (is_sre_array (mono_object_get_class(obj)) ||
13182                                 is_sre_byref (mono_object_get_class(obj)) ||
13183                                 is_sre_pointer (mono_object_get_class(obj))) {
13184                 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
13185                 MonoType *type = mono_reflection_type_get_handle (ref_type);
13186
13187                 if (context) {
13188                         MonoType *inflated = mono_class_inflate_generic_type (type, context);
13189                         result = mono_class_from_mono_type (inflated);
13190                         mono_metadata_free_type (inflated);
13191                 } else {
13192                         result = mono_class_from_mono_type (type);
13193                 }
13194                 *handle_class = mono_defaults.typehandle_class;
13195         } else {
13196                 g_print ("%s\n", obj->vtable->klass->name);
13197                 g_assert_not_reached ();
13198         }
13199         return result;
13200 }
13201
13202 #else /* DISABLE_REFLECTION_EMIT */
13203
13204 MonoArray*
13205 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
13206 {
13207         g_assert_not_reached ();
13208         return NULL;
13209 }
13210
13211 void
13212 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
13213 {
13214         g_assert_not_reached ();
13215 }
13216
13217 void
13218 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
13219 {
13220         g_assert_not_reached ();
13221 }
13222
13223 void
13224 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
13225 {
13226         g_assert_not_reached ();
13227 }
13228
13229 void
13230 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
13231 {
13232         g_assert_not_reached ();
13233 }
13234
13235 void
13236 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
13237 {
13238         g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
13239 }
13240
13241 void
13242 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
13243 {
13244         g_assert_not_reached ();
13245 }
13246
13247 void
13248 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
13249 {
13250         g_assert_not_reached ();
13251 }
13252
13253 MonoReflectionModule *
13254 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
13255 {
13256         g_assert_not_reached ();
13257         return NULL;
13258 }
13259
13260 guint32
13261 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
13262 {
13263         g_assert_not_reached ();
13264         return 0;
13265 }
13266
13267 guint32
13268 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types, MonoError *error)
13269 {
13270         g_assert_not_reached ();
13271         return 0;
13272 }
13273
13274 guint32
13275 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, 
13276                          gboolean create_open_instance, gboolean register_token, MonoError *error)
13277 {
13278         g_assert_not_reached ();
13279         return 0;
13280 }
13281
13282 void
13283 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
13284 {
13285 }
13286
13287 void
13288 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *fields)
13289 {
13290         g_assert_not_reached ();
13291 }
13292
13293 void
13294 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
13295 {
13296         *overrides = NULL;
13297         *num_overrides = 0;
13298 }
13299
13300 MonoReflectionEvent *
13301 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
13302 {
13303         g_assert_not_reached ();
13304         return NULL;
13305 }
13306
13307 MonoReflectionType*
13308 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
13309 {
13310         g_assert_not_reached ();
13311         return NULL;
13312 }
13313
13314 void
13315 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
13316 {
13317         g_assert_not_reached ();
13318 }
13319
13320 MonoArray *
13321 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
13322 {
13323         g_assert_not_reached ();
13324         return NULL;
13325 }
13326
13327 MonoArray *
13328 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
13329 {
13330         g_assert_not_reached ();
13331         return NULL;
13332 }
13333
13334 void 
13335 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
13336 {
13337 }
13338
13339 gpointer
13340 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
13341 {
13342         return NULL;
13343 }
13344
13345 MonoType*
13346 mono_reflection_type_get_handle (MonoReflectionType* ref)
13347 {
13348         if (!ref)
13349                 return NULL;
13350         return ref->type;
13351 }
13352
13353 void
13354 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
13355 {
13356         g_assert_not_reached ();
13357 }
13358
13359 #endif /* DISABLE_REFLECTION_EMIT */
13360
13361 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
13362 const static guint32 declsec_flags_map[] = {
13363         0x00000000,                                     /* empty */
13364         MONO_DECLSEC_FLAG_REQUEST,                      /* SECURITY_ACTION_REQUEST                      (x01) */
13365         MONO_DECLSEC_FLAG_DEMAND,                       /* SECURITY_ACTION_DEMAND                       (x02) */
13366         MONO_DECLSEC_FLAG_ASSERT,                       /* SECURITY_ACTION_ASSERT                       (x03) */
13367         MONO_DECLSEC_FLAG_DENY,                         /* SECURITY_ACTION_DENY                         (x04) */
13368         MONO_DECLSEC_FLAG_PERMITONLY,                   /* SECURITY_ACTION_PERMITONLY                   (x05) */
13369         MONO_DECLSEC_FLAG_LINKDEMAND,                   /* SECURITY_ACTION_LINKDEMAND                   (x06) */
13370         MONO_DECLSEC_FLAG_INHERITANCEDEMAND,            /* SECURITY_ACTION_INHERITANCEDEMAND            (x07) */
13371         MONO_DECLSEC_FLAG_REQUEST_MINIMUM,              /* SECURITY_ACTION_REQUEST_MINIMUM              (x08) */
13372         MONO_DECLSEC_FLAG_REQUEST_OPTIONAL,             /* SECURITY_ACTION_REQUEST_OPTIONAL             (x09) */
13373         MONO_DECLSEC_FLAG_REQUEST_REFUSE,               /* SECURITY_ACTION_REQUEST_REFUSE               (x0A) */
13374         MONO_DECLSEC_FLAG_PREJIT_GRANT,                 /* SECURITY_ACTION_PREJIT_GRANT                 (x0B) */
13375         MONO_DECLSEC_FLAG_PREJIT_DENY,                  /* SECURITY_ACTION_PREJIT_DENY                  (x0C) */
13376         MONO_DECLSEC_FLAG_NONCAS_DEMAND,                /* SECURITY_ACTION_NONCAS_DEMAND                (x0D) */
13377         MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND,            /* SECURITY_ACTION_NONCAS_LINKDEMAND            (x0E) */
13378         MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND,     /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND     (x0F) */
13379         MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE,            /* SECURITY_ACTION_LINKDEMAND_CHOICE            (x10) */
13380         MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE,     /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE     (x11) */
13381         MONO_DECLSEC_FLAG_DEMAND_CHOICE,                /* SECURITY_ACTION_DEMAND_CHOICE                (x12) */
13382 };
13383
13384 /*
13385  * Returns flags that includes all available security action associated to the handle.
13386  * @token: metadata token (either for a class or a method)
13387  * @image: image where resides the metadata.
13388  */
13389 static guint32
13390 mono_declsec_get_flags (MonoImage *image, guint32 token)
13391 {
13392         int index = mono_metadata_declsec_from_index (image, token);
13393         MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
13394         guint32 result = 0;
13395         guint32 action;
13396         int i;
13397
13398         /* HasSecurity can be present for other, not specially encoded, attributes,
13399            e.g. SuppressUnmanagedCodeSecurityAttribute */
13400         if (index < 0)
13401                 return 0;
13402
13403         for (i = index; i < t->rows; i++) {
13404                 guint32 cols [MONO_DECL_SECURITY_SIZE];
13405
13406                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13407                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13408                         break;
13409
13410                 action = cols [MONO_DECL_SECURITY_ACTION];
13411                 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
13412                         result |= declsec_flags_map [action];
13413                 } else {
13414                         g_assert_not_reached ();
13415                 }
13416         }
13417         return result;
13418 }
13419
13420 /*
13421  * Get the security actions (in the form of flags) associated with the specified method.
13422  *
13423  * @method: The method for which we want the declarative security flags.
13424  * Return the declarative security flags for the method (only).
13425  *
13426  * Note: To keep MonoMethod size down we do not cache the declarative security flags
13427  *       (except for the stack modifiers which are kept in the MonoJitInfo structure)
13428  */
13429 guint32
13430 mono_declsec_flags_from_method (MonoMethod *method)
13431 {
13432         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13433                 /* FIXME: No cache (for the moment) */
13434                 guint32 idx = mono_method_get_index (method);
13435                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13436                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13437                 return mono_declsec_get_flags (method->klass->image, idx);
13438         }
13439         return 0;
13440 }
13441
13442 /*
13443  * Get the security actions (in the form of flags) associated with the specified class.
13444  *
13445  * @klass: The class for which we want the declarative security flags.
13446  * Return the declarative security flags for the class.
13447  *
13448  * Note: We cache the flags inside the MonoClass structure as this will get 
13449  *       called very often (at least for each method).
13450  */
13451 guint32
13452 mono_declsec_flags_from_class (MonoClass *klass)
13453 {
13454         if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
13455                 if (!klass->ext || !klass->ext->declsec_flags) {
13456                         guint32 idx;
13457
13458                         idx = mono_metadata_token_index (klass->type_token);
13459                         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13460                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13461                         mono_loader_lock ();
13462                         mono_class_alloc_ext (klass);
13463                         mono_loader_unlock ();
13464                         /* we cache the flags on classes */
13465                         klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
13466                 }
13467                 return klass->ext->declsec_flags;
13468         }
13469         return 0;
13470 }
13471
13472 /*
13473  * Get the security actions (in the form of flags) associated with the specified assembly.
13474  *
13475  * @assembly: The assembly for which we want the declarative security flags.
13476  * Return the declarative security flags for the assembly.
13477  */
13478 guint32
13479 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
13480 {
13481         guint32 idx = 1; /* there is only one assembly */
13482         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13483         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13484         return mono_declsec_get_flags (assembly->image, idx);
13485 }
13486
13487
13488 /*
13489  * Fill actions for the specific index (which may either be an encoded class token or
13490  * an encoded method token) from the metadata image.
13491  * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
13492  */
13493 static MonoBoolean
13494 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
13495         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13496 {
13497         MonoBoolean result = FALSE;
13498         MonoTableInfo *t;
13499         guint32 cols [MONO_DECL_SECURITY_SIZE];
13500         int index = mono_metadata_declsec_from_index (image, token);
13501         int i;
13502
13503         t  = &image->tables [MONO_TABLE_DECLSECURITY];
13504         for (i = index; i < t->rows; i++) {
13505                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13506
13507                 if (cols [MONO_DECL_SECURITY_PARENT] != token)
13508                         return result;
13509
13510                 /* if present only replace (class) permissions with method permissions */
13511                 /* if empty accept either class or method permissions */
13512                 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
13513                         if (!actions->demand.blob) {
13514                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13515                                 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13516                                 actions->demand.blob = (char*) (blob + 2);
13517                                 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
13518                                 result = TRUE;
13519                         }
13520                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
13521                         if (!actions->noncasdemand.blob) {
13522                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13523                                 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13524                                 actions->noncasdemand.blob = (char*) (blob + 2);
13525                                 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
13526                                 result = TRUE;
13527                         }
13528                 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
13529                         if (!actions->demandchoice.blob) {
13530                                 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13531                                 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
13532                                 actions->demandchoice.blob = (char*) (blob + 2);
13533                                 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
13534                                 result = TRUE;
13535                         }
13536                 }
13537         }
13538
13539         return result;
13540 }
13541
13542 static MonoBoolean
13543 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands, 
13544         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13545 {
13546         guint32 idx = mono_metadata_token_index (klass->type_token);
13547         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13548         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13549         return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
13550 }
13551
13552 static MonoBoolean
13553 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands, 
13554         guint32 id_std, guint32 id_noncas, guint32 id_choice)
13555 {
13556         guint32 idx = mono_method_get_index (method);
13557         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13558         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13559         return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
13560 }
13561
13562 /*
13563  * Collect all actions (that requires to generate code in mini) assigned for
13564  * the specified method.
13565  * Note: Don't use the content of actions if the function return FALSE.
13566  */
13567 MonoBoolean
13568 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
13569 {
13570         guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND | 
13571                 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
13572         MonoBoolean result = FALSE;
13573         guint32 flags;
13574
13575         /* quick exit if no declarative security is present in the metadata */
13576         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13577                 return FALSE;
13578
13579         /* we want the original as the wrapper is "free" of the security informations */
13580         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13581                 method = mono_marshal_method_from_wrapper (method);
13582                 if (!method)
13583                         return FALSE;
13584         }
13585
13586         /* First we look for method-level attributes */
13587         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13588                 mono_class_init (method->klass);
13589                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13590
13591                 result = mono_declsec_get_method_demands_params (method, demands, 
13592                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13593         }
13594
13595         /* Here we use (or create) the class declarative cache to look for demands */
13596         flags = mono_declsec_flags_from_class (method->klass);
13597         if (flags & mask) {
13598                 if (!result) {
13599                         mono_class_init (method->klass);
13600                         memset (demands, 0, sizeof (MonoDeclSecurityActions));
13601                 }
13602                 result |= mono_declsec_get_class_demands_params (method->klass, demands, 
13603                         SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
13604         }
13605
13606         /* The boolean return value is used as a shortcut in case nothing needs to
13607            be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
13608         return result;
13609 }
13610
13611
13612 /*
13613  * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
13614  *
13615  * Note: Don't use the content of actions if the function return FALSE.
13616  */
13617 MonoBoolean
13618 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
13619 {
13620         MonoBoolean result = FALSE;
13621         guint32 flags;
13622
13623         /* quick exit if no declarative security is present in the metadata */
13624         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13625                 return FALSE;
13626
13627         /* we want the original as the wrapper is "free" of the security informations */
13628         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13629                 method = mono_marshal_method_from_wrapper (method);
13630                 if (!method)
13631                         return FALSE;
13632         }
13633
13634         /* results are independant - zeroize both */
13635         memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
13636         memset (klass, 0, sizeof (MonoDeclSecurityActions));
13637
13638         /* First we look for method-level attributes */
13639         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13640                 mono_class_init (method->klass);
13641
13642                 result = mono_declsec_get_method_demands_params (method, cmethod, 
13643                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13644         }
13645
13646         /* Here we use (or create) the class declarative cache to look for demands */
13647         flags = mono_declsec_flags_from_class (method->klass);
13648         if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
13649                 mono_class_init (method->klass);
13650
13651                 result |= mono_declsec_get_class_demands_params (method->klass, klass, 
13652                         SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
13653         }
13654
13655         return result;
13656 }
13657
13658 /*
13659  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13660  *
13661  * @klass       The inherited class - this is the class that provides the security check (attributes)
13662  * @demans      
13663  * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
13664  * 
13665  * Note: Don't use the content of actions if the function return FALSE.
13666  */
13667 MonoBoolean
13668 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
13669 {
13670         MonoBoolean result = FALSE;
13671         guint32 flags;
13672
13673         /* quick exit if no declarative security is present in the metadata */
13674         if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13675                 return FALSE;
13676
13677         /* Here we use (or create) the class declarative cache to look for demands */
13678         flags = mono_declsec_flags_from_class (klass);
13679         if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
13680                 mono_class_init (klass);
13681                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13682
13683                 result |= mono_declsec_get_class_demands_params (klass, demands, 
13684                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13685         }
13686
13687         return result;
13688 }
13689
13690 /*
13691  * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
13692  *
13693  * Note: Don't use the content of actions if the function return FALSE.
13694  */
13695 MonoBoolean
13696 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
13697 {
13698         /* quick exit if no declarative security is present in the metadata */
13699         if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
13700                 return FALSE;
13701
13702         /* we want the original as the wrapper is "free" of the security informations */
13703         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
13704                 method = mono_marshal_method_from_wrapper (method);
13705                 if (!method)
13706                         return FALSE;
13707         }
13708
13709         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13710                 mono_class_init (method->klass);
13711                 memset (demands, 0, sizeof (MonoDeclSecurityActions));
13712
13713                 return mono_declsec_get_method_demands_params (method, demands, 
13714                         SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
13715         }
13716         return FALSE;
13717 }
13718
13719
13720 static MonoBoolean
13721 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
13722 {
13723         guint32 cols [MONO_DECL_SECURITY_SIZE];
13724         MonoTableInfo *t;
13725         int i;
13726
13727         int index = mono_metadata_declsec_from_index (image, token);
13728         if (index == -1)
13729                 return FALSE;
13730
13731         t =  &image->tables [MONO_TABLE_DECLSECURITY];
13732         for (i = index; i < t->rows; i++) {
13733                 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
13734
13735                 /* shortcut - index are ordered */
13736                 if (token != cols [MONO_DECL_SECURITY_PARENT])
13737                         return FALSE;
13738
13739                 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
13740                         const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
13741                         entry->blob = (char*) (metadata + 2);
13742                         entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
13743                         return TRUE;
13744                 }
13745         }
13746
13747         return FALSE;
13748 }
13749
13750 MonoBoolean
13751 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
13752 {
13753         if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
13754                 guint32 idx = mono_method_get_index (method);
13755                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13756                 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
13757                 return get_declsec_action (method->klass->image, idx, action, entry);
13758         }
13759         return FALSE;
13760 }
13761
13762 MonoBoolean
13763 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
13764 {
13765         /* use cache */
13766         guint32 flags = mono_declsec_flags_from_class (klass);
13767         if (declsec_flags_map [action] & flags) {
13768                 guint32 idx = mono_metadata_token_index (klass->type_token);
13769                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
13770                 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
13771                 return get_declsec_action (klass->image, idx, action, entry);
13772         }
13773         return FALSE;
13774 }
13775
13776 MonoBoolean
13777 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
13778 {
13779         guint32 idx = 1; /* there is only one assembly */
13780         idx <<= MONO_HAS_DECL_SECURITY_BITS;
13781         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
13782
13783         return get_declsec_action (assembly->image, idx, action, entry);
13784 }
13785
13786 gboolean
13787 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
13788 {
13789         MonoError error;
13790         MonoObject *res, *exc;
13791         void *params [1];
13792         static MonoMethod *method = NULL;
13793
13794         if (method == NULL) {
13795                 method = mono_class_get_method_from_name (mono_class_get_type_builder_class (), "IsAssignableTo", 1);
13796                 g_assert (method);
13797         }
13798
13799         /* 
13800          * The result of mono_type_get_object_checked () might be a System.MonoType but we
13801          * need a TypeBuilder so use mono_class_get_ref_info (klass).
13802          */
13803         g_assert (mono_class_get_ref_info (klass));
13804         g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
13805
13806         params [0] = mono_type_get_object_checked (mono_domain_get (), &oklass->byval_arg, &error);
13807         mono_error_raise_exception (&error); /* FIXME don't raise here */
13808
13809         res = mono_runtime_try_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc, &error);
13810
13811         if (exc || !mono_error_ok (&error)) {
13812                 mono_error_cleanup (&error);
13813                 return FALSE;
13814         } else
13815                 return *(MonoBoolean*)mono_object_unbox (res);
13816 }
13817
13818 /**
13819  * mono_reflection_type_get_type:
13820  * @reftype: the System.Type object
13821  *
13822  * Returns the MonoType* associated with the C# System.Type object @reftype.
13823  */
13824 MonoType*
13825 mono_reflection_type_get_type (MonoReflectionType *reftype)
13826 {
13827         g_assert (reftype);
13828
13829         return mono_reflection_type_get_handle (reftype);
13830 }
13831
13832 /**
13833  * mono_reflection_assembly_get_assembly:
13834  * @refassembly: the System.Reflection.Assembly object
13835  *
13836  * Returns the MonoAssembly* associated with the C# System.Reflection.Assembly object @refassembly.
13837  */
13838 MonoAssembly*
13839 mono_reflection_assembly_get_assembly (MonoReflectionAssembly *refassembly)
13840 {
13841         g_assert (refassembly);
13842
13843         return refassembly->assembly;
13844 }
13845